Указатель на vtable обновляется при входе в каждый конструктор в иерархии, а затем снова при входе в каждый деструктор. Vptr начнет указывать на базовый класс, а затем будет обновляться по мере инициализации различных уровней.
Хотя вы и будете читать от многих людей, что это определяется реализацией, поскольку это полный выбор vtables, но факт заключается в том, что все компиляторы используют vtables, и как только вы выбираете подход vtable, стандарт требует, чтобы тип объекта времени выполнения - это тип выполняемого конструктора / деструктора , и это, в свою очередь, означает, что, какой бы ни был механизм динамической диспетчеризации, он должен быть отрегулирован по мере прохождения цепочки строительства / разрушения. *
Рассмотрим следующий фрагмент кода:
#include <iostream>
struct base;
void callback( base const & b );
struct base {
base() { callback( *this ); }
~base() { callback( *this ); }
virtual void f() const { std::cout << "base" << std::endl; }
};
struct derived : base {
derived() { callback( *this ); }
~derived() { callback( *this ); }
virtual void f() const { std::cout << "derived" << std::endl; }
};
void callback( base const & b ) {
b.f();
}
int main() {
derived d;
}
Стандарт предписывает, что выходные данные этой программы равны base
, derived
, derived
, base
, но вызов в callback
одинаков для всех четырех вызовов функции. Единственный способ, которым это может быть реализовано, - это обновить vptr в объекте в процессе строительства / разрушения.