Preparatory work
1. VS2012 use command line options to view the memory layout of an object
Microsoft Visual Studio provides the option for users to display the layout of C + + objects in memory:/d1reportsingleclasslayout. It's easy to use, just click on the "Visual properties " button under the [Project P] option. Switch to the CPP file in the directory where you can enter the following command
C1 [Filename].cpp /d1reportsingleclasslayout[classname]
Where [Filename].cpp is the CPP file where the class we want to view is located, [ClassName] refers to the class name we want to view. (The following examples illustrate ...) )
Virtual inheritance and virtual functions are two concepts that are completely unrelated.
Virtual inheritance is a means to solve the problem of multiple inheritance in C + +, the same base class inherited from different paths, there will be multiple copies in the subclass. There are two questions:
One is to waste storage space;
Second, there is a ambiguity, you can usually assign the address of a derived class object to a base class object, by pointing the base-class pointer at the address of the base class object in the inheriting class (The inheriting class has a copy of the base class), but multiple inheritance may have multiple copies of a base class, and there is a two ambiguity.
Virtual inheritance solves two of the problems mentioned earlier in the inheritance:
The underlying implementation principle of virtual inheritance is related to compiler, generally through virtual base class pointers and virtual base class table implementation, each virtual inheriting subclass has a virtual base class pointer (occupy a pointer of storage space, 4 bytes) and Virtual base class table (do not occupy the storage space of the class object) (need to emphasize that the virtual base class will still exist in the subclass of the copy, There is only one copy at most, not in the subclass, and the virtual base class pointer is inherited when the child class of the virtual inheritance is inherited as a parent class.
In fact, vbptr refers to the virtual base class table pointer (virtual table pointer), which points to a virtual base class table, which records the offset address of the virtual base class from this class, and the virtual base class member by the offset address. Virtual inheritance does not have to maintain the same two copies of the common base class (virtual base class) as the common multiple inheritance, saving storage space.
Here we can compare the implementation principle of virtual function: they have similarities, both use virtual pointers (both occupy the storage space of the class) and virtual table (all do not occupy the storage space of the class).
The virtual base class still exists in the inheriting class, occupying only storage space, and virtual function does not occupy storage space.
The Virtual base class table stores the offset of the virtual base class relative to the directly inheriting class, whereas the virtual function table stores the virtual function address.
Add:
1, D inherits the B,c also inherits two virtual base class pointer
2. The Virtual base class table stores the offset of the virtual base class relative to the direct inheriting class (d is not the direct inheriting class of the virtual base class, B,c is)
#if 0//test the existence of a virtual table # include <iostream>using namespace std;class a{int i = 10;int ia = 100;void func () {}virtual void run ( ) {cout << "A::run ()" << Endl;} virtual void run1 () {cout << "a::run1 ()" << Endl;} virtual void run2 () {cout << "a::run2 ()" << Endl;}}; Class b:public a{virtual void Run () {cout << "B::run ()" << Endl;} virtual void run1 () {cout << "b::run1 ()" << Endl;}}; Class C:p ublic a{virtual void Run () {cout << "C::run ()" << Endl;} virtual void run1 () {cout << "c::run1 ()" << Endl;} virtual void Run3 () {cout << "c::run3 ()" << Endl;}}; Class D:/*virtual*/public a{virtual void Run () {cout << "D::run ()" << Endl;} virtual void run1 () {cout << "d::run1 ()" << Endl;} virtual void run2 () {cout << "d::run2 ()" << Endl;} virtual void Run3 () {cout << "d::run3 ()" << Endl;}}; int Test () {cout << sizeof (A) << endl<< sizEOF (B) << endl<< sizeof (C) << endl<< sizeof (D) << endl;cout << sizeof (long Long) <& Lt endl;//a * PA = new d;d d;//d.run (); typedef void (*function) (void); int * * pvtable = (int *) &d; #if 0int * pvtable = (in t*) &d;int vtaleadress = *pvtable;int * ppvtable = (int*) vtaleadress;int func1 = *ppvtable; function F1 = (function) func1;f1 () #endif//pvtable[0][0]for (int idx = 0; Pvtable[0][idx]! = NULL; ++idx) {function f = (fun ction) pvtable[0][idx];f ();} cout << (int) pvtable[1] << endl;//cout << (int) pvtable[2] << Endl;getchar (); return 0;} int main (void) {test (); return 0;} #endif
Test one or two: different cases of a single inheritance
#if 0//Test One: A single virtual inheritance, without virtual function//virtual inheritance and inheritance of the difference//1. A virtual base pointer//2. Virtual base class is located at the end of the derived class storage space//test two: Single virtual inheritance with virtual function// 1. If the derived class does not have its own virtual function, At this point, the derived class object does not produce a// virtual function pointer// 2. If a derived class has its own virtual function, the derived class object generates its own virtual function pointer,// and the virtual function pointer is at the beginning of the derived class object storage//#pragma Vtordisp (off) #include <iostream>using std::cout;using std::endl;class a{public:a (): _ia (Ten) {}//virtualvoid F () {cout << "a::f ()" << Endl;} Private:int _ia;}; Class B: virtual public a{public:b (): _ib {}void fb () {cout << "A::FB ()" << Endl;} virtual void F () {cout << "b::f ()" << Endl;} #if 1virtual void Fb2 () {cout << "b::fb2 ()" << Endl;} #endifprivate: int _ib;}; int main (void) {cout << sizeof (A) << endl;cout << sizeof (B) << Endl; B B;getchar (); return 0;} #endif
Test Three: Multiple inheritance
Test Three: Multiple inheritance (with virtual function)//1. Each base class has its own virtual function table//2. If a derived class has its own virtual function, it is added to the first virtual function table//3. In memory layout, the layout of its base class is arranged in the order in which the base class is declared//4. The derived class overrides the virtual function of the base class, and only the first virtual function table holds the address of the//real overridden function, and the other virtual function table is not the actual//corresponding virtual function address, And just a jump instruction # if 1#pragma vtordisp (off) #include <iostream>using std::cout;using std::endl;class base1{public:base1 (): _ibase1 () {}/*virtual*/void F () {cout << "base1::f ()" << Endl;} /*virtual*/void G () {cout << "base1::g ()" << Endl;} /*virtual*/void H () {cout << "base1::h ()" << Endl;} Private:int _ibase1;}; Class Base2{public:base2 (): _ibase2 (+) {}virtual void F () {cout << "base2::f ()" << Endl;} /*virtual*/void G () {cout << "base2::g ()" << Endl;} /*virtual*/void H () {cout << "base2::h ()" << Endl;} Private:int _ibase2;}; Class Base3{public:base3 (): _ibase3 (+) {}virtual void F () {cout << "base3::f ()" << Endl;} /*virtual*/void G () {cout << "base3::g ()" << Endl;} /*virtual*/void H () {cout << "base3::h ()" << Endl;} Private:int _ibase3;}; Class Derived:virtual public base1//, Vsan base2//, Public base3{public:derived (): _iderived (10000) {}void f () {cout << "derived::f ()" << Endl;} /*virtual*/void G1 () {cout << "derived::g1 ()" << Endl;} Private:int _iderived;}; int main (void) {Derived D; Base1 b1;//base1 *pbase1 = &b1;//base2 * PBase2 = &d;//base3 * pBase3 = &d;derived * pderived = &d;//pbase 2->f (); cout << "sizeof (d) =" << sizeof (d) << endl;cout << "&derived =" << &d &l t;< Endl; These three address values are not the same//cout << "pBase1 =" << pBase1 << endl;//cout << "pBase2 =" << pBase2 <&l T Endl cout << "pBase3 =" << pBase3 << Endl; GetChar (); return 0;} #endif
Test four: diamond-Type Inheritance
Test four: Diamond type virtual Inheritance (Diamond Inheritance)//virtual base pointer pointing to the contents of the Virtual base table://1. The first content of the virtual base pointer represents the offset//2 of the first address of the child object where the virtual base pointer is located. The second content of the virtual base pointer represents the offset of the virtual base pointer from the first address of the virtual base class child object # if 0#pragma vtordisp (off) #include <iostream>using std::cout;using std:: Endl;class b{public:b (): _ib (Ten), _CB (' B ') {}virtual void F () {cout << "b::f ()" << Endl;} virtual void Bf () {cout << "B::BF ()" << Endl;} Private:int _ib;char _CB;}; Class B1:virtual Public b{public:b1 (): _IB1 (+), _CB1 (' 1 ') {}virtual void F () {cout << "b1::f ()" << Endl;} #if 1virtual void F1 () {cout << "b1::f1 ()" << Endl;} virtual void Bf1 () {cout << "b1::bf1 ()" << Endl;} #endifprivate: int _ib1;char _cb1;}; Class B2:virtual Public b{public:b2 (): _ib2 (+), _CB2 (' 2 ') {}virtual void F () {cout << "b2::f ()" << Endl;} #if 1virtual void F2 () {cout << "b2::f2 ()" << Endl;} virtual void Bf2 () {cout << "b2::bf2 ()" << Endl;} #endifprivate: int _ib2;char _cb2;}; Class D:public B1, Public b2{public:d (): _id (10000), _CD (' 3 ') {}virtual void F () {cout << "d::f ()" << Endl;} #if 1virtual void F1 () {cout << "d::f1 ()" << Endl;} virtual void F2 () {cout << "d::f2 ()" << Endl;} virtual void Df () {cout << "D::D F ()" << Endl;} #endifprivate: int _id;char _cd;}; int main (void) {D d;cout << sizeof (d) << Endl;getchar (); return 0;} #endif
A friend of the Tao can itself try each case in the case of program memory distribution in order to be clearer about the virtual function and virtual inheritance.
The virtual function and virtual inheritance of C + +