Рассмотрим следующую иерархию:
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; }
};
Какова точная схема памяти экземпляра C
? Сколько vptrs в нем содержится, где именно каждый из них размещен? Какие из виртуальных таблиц используются совместно с виртуальной таблицей C? Что именно содержит каждая виртуальная таблица?
Вот как я понимаю раскладку:
----------------------------------------------------------------
|vptr1 | AptrOfB1 | b1 | B2ptr | c | vptr2 | AptrOfB2 | b2 | a |
----------------------------------------------------------------
где AptrOfBx
— указатель на экземпляр A
, который Bx
содержит (, поскольку наследование является виртуальным ).
Это правильно? На какие функции указывает vptr1
? На какие функции указывает vptr2
?
Учитывая следующий код
C* c = new C();
dynamic_cast<B1*>(c)->f(3);
static_cast<B2*>(c)->f(3);
reinterpret_cast<B2*>(c)->f(3);
Почему все вызовы f
печатают 33
?