The virtual table structure in C + + class is an important knowledge point in C + + object model, here we will analyze the structure of the virtual table in memory.
C + + A class with virtual functions will have a virtual table pointer, which points to the corresponding virtual table, a general class will only have a virtual table, each virtual table has multiple "slots", each slot holds a virtual function address. The contents of the slot can be overwritten, and if the subclass overrides a virtual function in the parent class, the corresponding position in the slot is overwritten. A virtual table is a virtual function address, regardless of whether the virtual function is public or private. The light text description is not very image, the following example diagram of a virtual table structure:
As you can see from the diagram, the virtual table pointer does point to the virtual table structure, and there are many slots in the virtual table structure, and each slot points to a virtual function. So how to test with the program, please continue to see:
#include <iostream>
#include <cstdio>
using namespace Std;
Class Base {
Public
virtual void Test () {
cout << "Base.text ()" << Endl;
}
Public
int A;
};
Class Derived:public Base {
Public
virtual void Test () {
cout << "Derived.test ()" << Endl;
}
Public
int b;
};
typedef void (*PFUNC) ();
int main () {
Derived Derived;
Pfunc ptest; function pointers
Output derived and its member A/b address
printf ("Derived:%p\n", &derived);
printf ("DERIVED.A:%p\n", & (DERIVED.A));
printf ("DERIVED.B:%p\n", & (DERIVED.B));
Extract the address of test virtual function
int *p = (int *) * (int *) (&derived);
Ptest = (pfunc) *p;
Ptest ();
return 0;
}
Output results:
Note that the program was tested under the CentOS 7 64-bit system. In the program directly extract the test virtual function address, and then make the call, found that the call is indeed the Derived.test function, which also illustrates the virtual table structure of the memory layout.
Some interesting questions about the virtual table
When does a virtual table pointer be assigned a value?
#include <iostream>
using namespace Std;
Class Base
{
Public
Base () {
cout << "Base ()" << Endl;
Show ();
int *p = &b;
cout << "base::b:" << p << Endl;
p = (int *) ((char *) p-8);
cout << "base::vptr:" << *p << Endl;
virtual function address in base
cout << "*base::vptr:" << * (int *) *p << Endl;
cout << Endl;
}
virtual void Show () {
cout << "Base::show ()" << Endl;
}
Public
int b;
};
Class Derived:public Base
{
Public
Derived ()
{
cout << "Derived ()" << Endl;
Show ();
int *p = &b;
cout << "derived::b:" << p << Endl;
p = (int *) ((char *) p-8);
cout << "derived::vptr:" << *p << Endl;
Virtual function address in derived
cout << "*derived::vptr:" << * (int *) *p << Endl;
cout << Endl;
}
virtual void Show () {
cout << "Derived::show ()" << Endl;
}
Private
int D;
};
int main (int argc, char **argv)
{
Base base;
Derived Derived;
return 0;
}
From the output results, it can be concluded that the virtual table pointer is assigned 2 times during the construction process. Initialized as follows:
base class static member-Subclass static member-(set v_ptr/base class member variable)-base class constructor-(set v_ptr/subclass member variable)-subclass constructor
Do you assign a virtual table pointer to a destructor in a class?
In a destructor of a subclass, the virtual table pointer is set to point to a virtual function address in the parent class, so calling a virtual function in the parent class's destructor actually calls the virtual function of the parent class, but generally does not. How to test it, follow the test code for the last question, and then make a little change to test it.