Consider following hierarchy:
struct A {
int a;
A() { f(0); }
A(int i) { f(i); }
virtual void f(int i) { cout << i; }
};
struct B1 : virtual A {
int b1;
B1(int i) : A(i) { f(i); }
virtual void f(int i) { cout << i+10; }
};
struct B2 : virtual A {
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; }
};
What's the exact memory layout of
C
instance? How many vptrs it contains, where exactly each of them is placed? Which of virtual tables are shared with virtual table of C? What exactly each virtual table contains?Here how I understand the layout:
---------------------------------------------------------------- |vptr1 | AptrOfB1 | b1 | B2ptr | c | vptr2 | AptrOfB2 | b2 | a | ----------------------------------------------------------------
where
AptrOfBx
is the pointer toA
instance thatBx
contains (since the inheritance is virtual).
Is that correct? Which functionsvptr1
points to? Which functionsvptr2
points to?Given the 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 all the calls to
f
print33
?
C foo; intptr_t offsetB1 = (intptr_t)(B1*)&foo - (intptr_t)&foo;
, the starts of the other bases can be derived analogously. Also, computing thesizeof
of all classes should give you another good clue. – Billibilliard