Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on Aug 10th, 2012  |  syntax: None  |  size: 5.60 KB  |  hits: 8  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. C   multiple inheritance and vtables
  2. // Includes
  3. #include <windows.h>
  4. #include <iostream>
  5.  
  6. interface A
  7. {
  8. public:
  9.     virtual void OutA() = 0;
  10. };
  11.  
  12. interface B
  13. {
  14. public:
  15.     virtual void OutB() = 0;
  16. };
  17.  
  18. class C : public A, public B
  19. {
  20. public:
  21.     void OutA();
  22.     void OutB();
  23. };
  24.  
  25. void C::OutA()
  26. {
  27.     printf("Out An");
  28. }
  29.  
  30. void C::OutB()
  31. {
  32.     printf("Out Bn");
  33. }
  34.  
  35. int main()
  36. {
  37.     C obj;
  38.     obj.OutA();
  39.     obj.OutB();
  40.  
  41.     A* ap = (A*)&obj;
  42.     B* bp = (B*)&obj;
  43.  
  44.     ap->OutA();
  45.     bp->OutB();
  46.  
  47.     system("pause");
  48.  
  49.     // Return
  50.     return 0;
  51. }
  52.        
  53. Out A
  54. Out B
  55. Out A
  56. Out B
  57.        
  58. #include <stdio.h>
  59. #include <stddef.h>
  60. #include <stdlib.h>
  61.  
  62. const int debug = 0;
  63.  
  64. void __pure_virtual_called() {
  65.     fputs ("pure virtual function calledn", stderr);
  66.     abort();
  67. }
  68.  
  69. /* Translation of:
  70.  
  71. class A
  72. {
  73. public:
  74.     virtual void OutA() = 0;
  75. };
  76. */
  77.  
  78. struct A;
  79.  
  80. typedef struct  {
  81.     void (*ptr__OutA) (struct A *__this);
  82. } vtable__A;
  83.  
  84. typedef struct A {
  85.     vtable__A *__vptr;
  86. } A;
  87.  
  88. /* translation A::OutA()
  89.  * pure virtual function */
  90. void A__OutA (A *__this) {
  91.      __pure_virtual_called();
  92. }
  93.  
  94. vtable__A vtable__A__A = { .ptr__OutA = A__OutA };
  95.  
  96. void A__constructor (A *__this) {
  97.     if (debug)
  98.         printf ("A__constructor %pn", (void*)__this);
  99.  
  100.     /* dynamic type is initialised to A */
  101.     __this->__vptr = &vtable__A__A;
  102. }
  103.  
  104. /* Translation of:
  105.  
  106. class B
  107. {
  108. public:
  109.     virtual void OutB() = 0;
  110. };
  111.  
  112. */
  113.  
  114. struct B;
  115.  
  116. typedef struct {
  117.     void (*ptr__OutB)(struct B *__this);
  118. } vtable__B;
  119.  
  120. typedef struct B {
  121.     vtable__B *__vptr;
  122. } B;
  123.  
  124. /* translation B::OutB()
  125.  * pure virtual function */
  126. void B__OutB (B *__this) {
  127.      __pure_virtual_called();
  128. }
  129.  
  130. vtable__B vtable__B__B = { .ptr__OutB = B__OutB };
  131.  
  132. void B__constructor (B *__this) {
  133.     if (debug)
  134.         printf ("B__constructor %pn", (void*)__this);
  135.  
  136.     /* dynamic type is initialised to B */
  137.     __this->__vptr = &vtable__B__B;
  138. }
  139. /* Translation of:
  140.  
  141. class C : public A, public B
  142. {
  143. public:
  144.     void OutA(); // overrides A::OutA()
  145.     void OutB(); // overrides B::OutB()
  146.     // note :
  147.     // no new virtual function
  148. };
  149.  
  150. */
  151.  
  152. /* no new virtual function
  153.  * so no specific vtable type! */
  154.  
  155. typedef struct {
  156. /* no additional vptr, we already have 2! */
  157.     A base__A;
  158.     B base__B;
  159. } C;
  160.  
  161. /******* upcasts
  162.  * translation of
  163.  * static_cast<C*> (p)
  164.  */
  165.  
  166. /* translation of
  167.  * A *p;
  168.  * static_cast<C*> (p);
  169.  */
  170. C *static_cast__A__C (A *__ptr) {
  171.     /*
  172.      * base__A is first member of C
  173.      * so offsetof(C, base__A) == 0
  174.      * can skip the pointer adjustment
  175.      */
  176.     return (C*)__ptr;
  177. }
  178.  
  179. /* translation of
  180.  * B *p;
  181.  * static_cast<C*> (p);
  182.  */
  183. C *static_cast__B__C (B *__ptr) {
  184.     /* locate enclosing C object:
  185.      * __base__B is not first member
  186.      * need to adjust pointer
  187.      */
  188.     return (C*)((char*)__ptr - offsetof(C, base__B));
  189. }
  190.  
  191. /* translation of virtual functions of C
  192.  * overriding function declarations from A
  193.  */
  194.  
  195. /* translation of C::OutA() */
  196.  
  197. /* C::OutA() called from C */
  198. void C__OutA (C *__this) {
  199.     printf("Out A this=%pn", (void*)__this);
  200. }
  201.  
  202. /* C::OutA() called from A */
  203. void C__A__OutA (A *__this) {
  204.     if (debug)
  205.             printf ("C__A__OutA %pn", (void*)__this);
  206.     C__OutA (static_cast__A__C (__this));
  207. }
  208.  
  209. vtable__A vtable__A__C = { .ptr__OutA = C__A__OutA };
  210.  
  211. /* translation of virtual functions of C
  212.  * overriding function declarations from B
  213.  */
  214.  
  215. /* translation of C::OutB() */
  216.  
  217. /* C::OutB() called from C */
  218. void C__OutB (C *__this) {
  219.     printf("Out B this=%pn", (void*)__this);
  220. }
  221.  
  222. /* C::OutB() called from B */
  223. void C__B__OutB (B *__this) {
  224.     if (debug)
  225.             printf ("C__B__OutB %pn", (void*)__this);
  226.     C__OutB (static_cast__B__C (__this));
  227. }
  228.  
  229. vtable__B vtable__B__C = { .ptr__OutB = C__B__OutB };
  230.  
  231. void C__constructor (C *__this) {
  232.     if (debug)
  233.         printf ("C__constructor %pn", (void*)__this);
  234.     /* construct subobjects */
  235.     A__constructor (&__this->base__A);
  236.     B__constructor (&__this->base__B);
  237.  
  238.     /* adjust dynamic type of this to C */
  239.     __this->base__A.__vptr = &vtable__A__C;
  240.     __this->base__B.__vptr = &vtable__B__C;
  241. }
  242.  
  243. /* calls to C virtual functions with a C*
  244.  */
  245.  
  246. /* translation of
  247.  * C *p;
  248.  * p->OutA();
  249.  *
  250.  * is
  251.  * ((A*)p)->OutA();
  252.  *
  253.  * because C::OutA() is overrides A::OutA()
  254.  */
  255. void dyn__C__OutA (C *__this) {
  256.     A *base_ptr__A = &__this->base__A;
  257.     base_ptr__A->__vptr->ptr__OutA (base_ptr__A);
  258. }
  259.  
  260. /* translation of
  261.  
  262. int main()
  263. {
  264.     C obj;
  265.     obj.OutA();
  266.     obj.OutB();
  267.  
  268.     A *ap = &obj;
  269.     B *bp = &obj;
  270.     C *cp = &obj;
  271.  
  272.     ap->OutA();
  273.     bp->OutB();
  274.     cp->OutA();
  275.  
  276.     // Return
  277.     return 0;
  278. }
  279.  
  280.  *
  281.  */
  282.  
  283. int main () {
  284.     /* translation of:
  285.     C obj;
  286.     */
  287.     C obj;
  288.     C__constructor (&obj);
  289.  
  290.     /* translation of:
  291.     obj.OutA();
  292.     obj.OutB();
  293.      * obj is a locally declared object
  294.      * so dynamic type of obj is known as C
  295.      * can make direct call to C::OutA(), C::OutB()
  296.      */
  297.     C__OutA (&obj);
  298.     C__OutB (&obj);
  299.  
  300.     /* dumb (zero optimisation) translation of:
  301.     A *ap = &obj;
  302.     B *bp = &obj;
  303.     C *cp = &obj;
  304.     */
  305.     A *ap = &obj.base__A;
  306.     B *bp = &obj.base__B;
  307.     C *cp = &obj;
  308.  
  309.     /* translation of:
  310.     ap->OutA();
  311.     bp->OutB();
  312.     cp->OutA();
  313.  
  314.     * dumb compiler = no optimisation
  315.     * so dynamic type of *ap, *bp, *cp is unknown
  316.     * so make "virtual" calls using vtable
  317.     */
  318.     ap->__vptr->ptr__OutA(ap);
  319.     bp->__vptr->ptr__OutB(bp);
  320.     dyn__C__OutA (cp);
  321.  
  322.     /* note: obj lifetime ends now
  323.      * C has a trivial destructor
  324.      * so no destructor call needed
  325.      */
  326.  
  327.     return 0;
  328. }
  329.        
  330. Out A this=0xbfeee2ec
  331. Out B this=0xbfeee2ec
  332. Out A this=0xbfeee2ec
  333. Out B this=0xbfeee2ec
  334. Out A this=0xbfeee2ec
  335.        
  336. C obj;
  337. A* ap = (A*)&obj;
  338. B* bp = (B*)&obj;
  339. bool same = ((void*)ap) == ((void*)bp);  // false!