#include <iostream>
using namespace std;
class Base {
public:
Base() {
cout << "In Base" << endl;
cout << "Virtual Pointer = " << (int*)this << endl;
cout << "Address of Vtable = "
<< (int*)*(int*)this << endl;
cout << "Value at Vtable = "
<< (int*)*(int*)*(int*)this << endl;
cout << endl;
}
virtual void f1() { cout << "Base::f1" << endl; }
};
class Drive : public Base {
public:
Drive() {
cout << "In Drive" << endl;
cout << "Virtual Pointer = "
<< (int*)this << endl;
cout << "Address of Vtable = "
<< (int*)*(int*)this << endl;
cout << "Value at Vtable = "
<< (int*)*(int*)*(int*)this << endl;
cout << endl;
}
virtual void f1() { cout << "Drive::f2" << endl; }
};
int main() {
Drive d;
return 0;
}
The output of this program is
In Base
Virtual Pointer = 0012FF7C
Address of Vtable = 0046C08C
Value at Vtable = 004010F0
In Drive
Virtual Pointer = 0012FF7C
Address of Vtable = 0046C07C
Value at Vtable = 00401217
Follow the code, i can see that when i create a Drive object, the Base constructor also run and show the address of virtual pointer same with Drive’s virtual pointer: 0012FF7C. The weird thing is that when i dereference that address in both constructors of Base and Drive class, it pointed to different value meaning there are two vtable, one at 0046C08C and another at 0046C07C. Its very difficult to understand in structure of Drive object and also in c langue when 1 pointer point 2 address.
You’ve just witnessed how your C++ compiler implements the rules set out by the C++ standard. While the
Baseconstructor is running, any calls to virtual methods need to be dispatched to theBaseimplementations, even ifDriveoverrides them. To make that happen, your C++ compiler evidently makes the object’s vtable pointer point to theBasevtable. When theBaseconstructor finishes and execution continues in theDriveconstructor, the vtable pointer gets updated to point at theDrivevtable.That ends up being a convenient way to implement it. The rest of code, where the compiler generates instructions to call virtual methods, doesn’t need to change to detect whether the special constructor behavior is required. It can just look in the vtable like always. Changing the vtable pointer is a quick way to change the effective run-time type of the object while the constructors run.
You’ll probably find the destructors work in a similar manner, but in reverse. If you construct a
Baseobject instead of aDriveobject, you’ll probably see similar addresses as you do in theBaseconstructor of yourDriveobject.