Polymorphism is an important feature of object-oriented programming in C + +. I used to see the virtual function is very magical, why can realize polymorphism. Initially, it was assumed that in order to implement Run-time polymorphism, a part of the object should always point to a fixed address, and when the subclass inherits, the contents of the address are modified. In this way, both the parent class and the subclass are going to the same fixed address to read the content and behave differently at run time.
After reading the "Deep Exploration of C + + object Model", the discovery idea is similar. In the object, there is a pointer to a virtual function table, in which every virtual function is stored in order, and when the subclass inherits, the function address is changed to the specified position of the virtual function table. When we manipulate a subclass through the parent pointer, the virtual function is called by the virtual function table + fixed offset, so the run-time polymorphism is realized.
In the depth of the book, the virtual function table is mostly placed at the end of the object, do not know what the current compiler is, so this article to actually do an experiment test.
Experimental environment: VC2013 Express
The code is as follows:
Class Parent {Public:int parent;
Parent (): parent (a) {} virtual void A () {cout << "parent::a ()" << Endl;}
virtual void B () {cout << "parent::b ()" << Endl;}
virtual void C () {cout << "parent::c ()" << Endl;};
Class Child:public Parent {public:int child;
Child (): Child (m) {} virtual void A () {cout << "child::a ()" << Endl;}
virtual void B_child () {cout << "child::b_child ()" << Endl;}
virtual void C_child () {cout << "child::c_child ()" << Endl;};
Class Grandchild:public child{public:int grandchild;
Grandchild (): grandchild (1000) {} virtual void A () {cout << "grandchild::a ()" << Endl;}
virtual void B_child () {cout << "grandchild::b_child ()" << Endl;}
virtual void C_grandchild () {cout << "grandchild::c_grandchild ()" << Endl;};
int main () {typedef void (*FUNC) ();
grandchild grandchild; int **vtable = (int * * *) &gRandchild; for (int i = 0; (func) vtable[0][i]!= nullptr;
i++) {Auto Pfunc = (func) vtable[0][i];
cout << "[<<i<<]";
Pfunc ();
return 0;
}
The results appear as shown in the following illustration:
Indeed, the virtual function table pointer starts at the beginning of the object and sees that the corresponding item is overwritten.