Привет,
Хочу разобраться в следующем вопросе.
class A
{
public:
virtual ~A() {}
virtual void foo() const { cout << "A::foo()" << endl; }
virtual void bar() const { cout << "A::bar()" << endl; }
};
class B : public A
{
public:
virtual ~B() {}
virtual void foo() const { cout << "B::foo()" << endl; }
virtual void bar() const { cout << "B::bar()" << endl; }
virtual void baz() const { cout << "B::baz()" << endl; }
};
A * pA = new B;
pA->baz(); // <-- тут естественно ошибка при компиляции
Вопрос: Понятно, что на выделенной строке будет ошибка при компиляции, хочу понять в деталях как этот механизм работает. При создании объекта класса A вызовется конструктор А, который запишет в vptr адрес vtable класса А. Далее конструктор B перезапишет vptr объекта адресом vtable класса B. vptr у объекта один и тут пока все просто. Далее при вызове виртуальных функwий через pA используется vptr, указывающий на vtable класса B, в котором уже есть адрес метода baz с индексом 2, т.е. формально в используемой vtable все же есть адрес нужной функции.
Далее как я это себе представляю: при кастинге B к А, vtable берется от B, но "урезается" до размера vtable класса А, поэтому при компиляции индекса метода baz в vtable не "обнаруживается". Как это все работает на самом деле?