The virtual table structure in C + + classes is an important point of knowledge in the C + + object model, where we 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, generally a class will only have a virtual table, each virtual table has more than one "slot", each slot holds the address of a virtual function. The contents of the slot can be overwritten, and if the subclass overrides the virtual function in the parent class, the data in the corresponding position in the slot is overwritten. A virtual table holds a virtual function address, whether the virtual function is public or private. Light text description is not very image, the following example of a virtual table structure diagram:
As you can see, the virtual table pointer does point to the virtual table structure, which has many slots in it, each pointing to a virtual function. So how to use the program to test it, please continue to look:
1#include <iostream>2#include <cstdio>3 4 using namespacestd;5 6 classBase {7 Public:8 Virtual voidTest () {9cout <<"Base.text ()"<<Endl;Ten } One A Public: - intA; - }; the - classDerived: PublicBase { - Public: - Virtual voidTest () { +cout <<"derived.test ()"<<Endl; - } + A Public: at intb; - }; - -typedefvoid(*PFunc) (); - - intMain () { in Derived Derived; -PFunc ptest;//function Pointers to + //output derived and its member A/b address -printf"Derived:%p\n", &derived); theprintf"derived.a:%p\n", &(DERIVED.A)); *printf"derived.b:%p\n", &(DERIVED.B)); $ Panax Notoginseng //Extract the test virtual function address - int*p = (int*)*(int*) (&derived); thePtest = (PFunc) *p; + ptest (); A the return 0; +}
Output Result:
Note that the program was tested under the CentOS 7 64-bit system. The program directly extracts the test virtual function address, and then make the call, found that the call is indeed the Derived.test function, which also shows the virtual table structure of the memory layout.
Some interesting questions about the virtual table
When does a virtual table pointer assign a value?
1#include <iostream>2 3 using namespacestd;4 5 classBase6 {7 Public:8 Base () {9cout <<"Base ()"<<Endl;Ten Show (); One int*p = &b; Acout <<"base::b:"<< P <<Endl; -p = (int*)((Char*) P-8); -cout <<"base::vptr:"<< *p <<Endl; the //virtual function address in base -cout <<"*base::vptr:"<< * (int*) *p <<Endl; -cout <<Endl; - } + - Virtual voidShow () { +cout <<"base::show ()"<<Endl; A } at Public: - intb; - }; - classDerived: PublicBase - { - Public: in Derived () - { tocout <<"Derived ()"<<Endl; + Show (); - int*p = &b; thecout <<"derived::b:"<< P <<Endl; *p = (int*)((Char*) P-8); $cout <<"derived::vptr:"<< *p <<Endl;Panax Notoginseng //virtual function address in derived -cout <<"*derived::vptr:"<< * (int*) *p <<Endl; thecout <<Endl; + } A Virtual voidShow () { thecout <<"derived::show ()"<<Endl; + } - Private: $ intD; $ }; - - intMainintargcChar**argv) the { -BaseBase;Wuyi Derived Derived; the - return 0; Wu}
The output is:
From the output results, it can be concluded that the virtual table pointer is assigned 2 times during the construction process. Initialize as follows:
base class static member – Subclass static member – (set v_ptr/base class member variable) – base class constructor – (set v_ptr/child class member variable) – subclass constructor
is the virtual table pointer assigned to the destructor of the class?
In the destructor of a subclass, the virtual table pointer is set to point to the virtual function address in the parent class, so calling the virtual function in the destructor of the parent class actually calls the virtual function of the parent class, but generally does not do so. How to test it, follow the test code for the last question, and then change it a little bit to test it.
Reference:
1. In-depth understanding of C + + object model
2. "Deep Exploration of C + + object Model"
Uncover the "mystery" of virtual tables in C + + classes