c++ - Virtual tables and memory layout in multiple virtual inheritance -


consider following hierarchy:

struct {    int a;     a() { f(0); }    a(int i) { f(i); }    virtual void f(int i) { cout << i; } }; struct b1 : virtual {    int b1;    b1(int i) : a(i) { f(i); }    virtual void f(int i) { cout << i+10; } }; struct b2 : virtual {    int b2;    b2(int i) : a(i) { f(i); }    virtual void f(int i) { cout << i+20; } }; struct c : b1, virtual b2 {    int c;    c() : b1(6),b2(3),a(1){}    virtual void f(int i) { cout << i+30; } }; 
  1. what's exact memory layout of c instance? how many vptrs contains, each of them placed? of virtual tables shared virtual table of c? each virtual table contains?

    here how understand layout:

    ---------------------------------------------------------------- |vptr1 | aptrofb1 | b1 | b2ptr | c | vptr2 | aptrofb2 | b2 | | ---------------------------------------------------------------- 

    where aptrofbx pointer a instance bx contains (since inheritance virtual).
    correct? functions vptr1 points to? functions vptr2 points to?

  2. given following code

    c* c = new c(); dynamic_cast<b1*>(c)->f(3); static_cast<b2*>(c)->f(3); reinterpret_cast<b2*>(c)->f(3); 

    why calls f print 33?

virtual bases different ordinary bases. remember "virtual" means "determined @ runtime" -- entire base subobject must determined @ runtime.

imagine getting b & x reference, , tasked find a::a member. if inheritance real, b has superclass a, , b-object viewing through x has a-subobject in can locate member a::a. if most-derived object of x has multiple bases of type a, can see particular copy subobject of b.

but if inheritance virtual, none of makes sense. don't know which a-subobject need -- information doesn't exist @ compile time. dealing actual b-object in b y; b & x = y;, or c-object c z; b & x = z;, or entirely different derives virtually a many more times. way know find actual base a at runtime.

this can implemented 1 more level of runtime indirection. (note how entirely parallel how virtual functions implemented 1 level of runtime indirection compared non-virtual functions.) instead of having pointer vtable or base subobject, 1 solution store pointer to pointer actual base subobject. called "thunk" or "trampoline".

so actual object c z; may follows. actual ordering in memory compiler , unimportant, , i've suppressed vtables.

+-+------++-+------++-----++-----+ |t|  b1  ||t|  b2  ||  c  ||   | +-+------++-+------++-----++-----+  |         |                 |  v         v                 ^  |         |       +-thunk-+ |  +--->>----+-->>---|     ->>-+                    +-------+ 

thus, no matter whether have b1& or b2&, first thunk, , 1 in turn tells find actual base subobject. explains why cannot perform static cast a& of derived types: information doesn't exist @ compile time.

for more in-depth explanation, take @ this fine article. (in description, thunk part of vtable of c, , virtual inheritance necessitates maintenance of vtables, if there no virtual functions anywhere.)


Comments