When exactly does the virtual table pointer (in C++) gets set for an object?
This is strictly Implementation dependent.
For Most compilers,
The compiler initializes this->__vptr within each constructor's Member Initializer list.
The idea is to cause each object's v-pointer to point at its class's v-table, and the compiler generates the hidden code for this and adds it to the constructor code. Something like:
Base::Base(...arbitrary params...)
: __vptr(&Base::__vtable[0]) ← supplied by the compiler, hidden from the programmer
{
}
This C++ FAQ explains a gist of what exactly happens.
This msdn article explains it in great detali
There it says :
"And the final answer is... as you'd expect. It happens in the constructor."
If I might add, right at the beginning of the constructor, before any other code you might have in your constructor gets executed.
But be careful, let's say you have the class A, and a class A1 derived from A.
- If you create a new A object, the vptr will be set right at the beginning of the constructor of the A class
- But if you create a new object A1:
"Here's the entire sequence of events when you construct an instance of class A1:
- A1::A1 calls A::A
- A::A sets vtable to A's vtable
- A::A executes and returns
- A1::A1 sets vtable to A1's vtable
- A1::A1 executes and returns "
The pointer to the vtable is updated on entry to each constructor in the hierarchy and then again on entry of each destructor. The vptr will start pointing to the base class, and then will be updated as the different levels are initialized.
While you will read from many different people that this is implementation defined, as it is the whole choice of vtables, but the fact is that all compilers use vtables, and once you choose a vtable approach, the standard does mandate that the type of the runtime object is that of the constructor/destructor being executed, and that in turn means that whatever the dynamic dispatch mechanism is, it has to be adjusted as the construction/destruction chain is traversed.
Consider the following code snippet:
#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;
}
The standard mandates that the output of that program is base
, derived
, derived
, base
, but the call in callback
is the same from all the four calls to the function. The only way that it can be implemented is by updating the vptr in the object as construction / destruction progresses.