1. Single- inheritance object Model
(1) Single inheritance
On the model of "programming experiment" inheriting object
#include <iostream>using namespacestd;classdemo{protected: intmi; intMJ; Public: //Virtual Functions Virtual voidprint () {cout<<"mi ="<< mi <<", "<<"MJ ="<< MJ <<Endl; } };classDerived: Publicdemo{intMk; Public: Derived (intIintJintk) {mi=i; MJ=J; Mk=K; } voidprint () {cout<<"mi ="<< mi <<", "<<"MJ ="<< MJ <<", "<<"mk ="<< Mk <<Endl; }};structtest{void*p; intmi; intMJ; intmk;};intMain () {cout<<"sizeof (Demo) ="<<sizeof(Demo) << Endl;//12, not 8, because a virtual function table pointer was insertedcout <<"sizeof (Derived) ="<<sizeof(Derived) << Endl;//16, not 12, for the same reason.Derived D (1,2,3); Test* p = reinterpret_cast<test*> (&d); cout<<Endl; //The following experiment proves that the memory model of derived with virtual function is consistent with the test structure .//1, the same size. 2, the 1th member variable is the vptr pointer, 3, the next is MI, MJ, Mkcout <<"before change ..."<<Endl; D.print (); P->mi =Ten; P->MJ = -; P->MK = -; cout<<" after change ..."<<Endl; D.print (); return 0;}/*output: sizeof (Demo) = 12sizeof (Derived) = 16Before CHANGE...MI = 1, MJ = 2, mk = 3After CHANGE...MI = ten, MJ =, mk = -*/
View Code
(2) Memory layout of derived objects
"Instance analysis" single inheritance
classbase{ Public: Base () {mBase1=101; MBase2=102; } Virtual voidfunc1 () {cout<<"base::func1 ()"<<Endl; } Virtual voidFunc2 () {cout<<"Base::func2 ()"<<Endl; } Private: intmBase1; intMBase2;};classDerived: Publicbase{ Public: Derived (): Base () {mDerived1=1001; MDerived2=1002; } Virtual voidFunc2 () {cout<<"Derived::func2 ()"<<Endl; } Virtual voidfunc3 () {cout<<"derived::func3 ()"<<Endl; } Private: intmDerived1; intmDerived2;};
(3) Conclusion
①Vptr is located at the forefront of the object, and non-static members are then ranked according to their inheritance order and declaration order.
The ② subclass inherits the virtual function declared by the base class, that is, the virtual function address of the base class is copied to the corresponding item in the virtual function table of the derived class. ( that is, the subclass has its own independent table of virtual functions )
The newly added virtual function in the ③ subclass follows the virtual following its inheritance. As in this example, the func3 virtual function is added after Func2.
④ if the subclass overrides the virtual function of the parent class , the item corresponding to the virtual function table of the child class is updated to the address of the new function. In this example, the subclass overrides the FUNC2 virtual function, and the FUNC2 item in the virtual function table is updated to the address of the function Func2 that the subclass overrides .
2. Multiple- inheritance object Model
(1) Multiple inheritance
"Instance analysis" multiple inheritance
classbase1{ Public: Base1 () {mBase1=101; } Virtual voidFunca () {cout<<"Base1::funca ()"<<Endl; } Virtual voidFUNCB () {cout<<"BASE1::FUNCB ()"<<Endl; } Private: intmBase1;};classbase2{ Public: Base2 () {MBase2=102; } Virtual voidFunca () {cout<<"Base2::funca ()"<<Endl; } Virtual voidFUNCC () {cout<<"BASE2::FUNCC ()"<<Endl; } Private: intMBase2;};classDerived: PublicBASE1, Publicbase2{ Public: Derived (): Base1 (), Base2 () {mderived=1001; } Virtual voidFuncd () {cout<<"DERIVED::FUNCD ()"<<Endl; } Virtual voidFunca () {cout<<"Derived::funca ()"<<Endl; } Private: intmderived;};
(2) Memory layout of derived objects
(3) Conclusion
Under ①n inheritance, subclasses will have n virtual function tables . 1 of these are primary tables, shared with the 1th base class (Base1 in this example) , and others as secondary tables, related to other base classes (such as Base2 in this example)
The virtual function of the new declaration of the ② subclass is placed in the main virtual function table . As in this example, the subclass is newly declared with the base shared virtual function table.
③ objects of each parent class remain as they are in the subclass, and then sequentially in the order in which they are declared.
④ if the subclass overrides the virtual function, the virtual function with the same signature in all its parent classes will be overwritten . In this case, the subclass overrides the Funca function, and the entries for the Funca function in the two virtual function table are updated to the address of the function that the subclass overrides. The purpose of this is to resolve pointers to different parent class types to the same child class object, and to invoke the actual function .
3. Description of the virtual destructor
(1) if a virtual destructor is declared by the parent class , the destructor of its subclass updates the item of the destructor in all its virtual function tables , updating the address of the function in the item to the address of the subclass's destructor.
(2) because when the destructor of the parent class is virtual, if the user does not explicitly provide a destructor, the compiler will automatically synthesize one, so if the parent declares a virtual destructor, there must be a virtual destructor in the subclass of the class, Use this virtual destructor to update the virtual function table.
4. The principle of polymorphism
(1) polymorphic: When a virtual function is called when a parent pointer (or reference) is used, a polymorphic
base* P;......P//Vfunc is the virtual function declared in base
(2) polymorphic principle:
① because the pointer p can point to a base object , or to an object of its derived class , and the compiler does not know at compile time what the real object that P is pointing to, then how to judge?
② from the memory distribution map of C + + objects, although the address of a virtual function table may be updated, the index value in the virtual function table of the virtual function that is the same signature between the parent and subclass is unchanged . So whether P points to a base object or to an object of its derived class, the virtual function vfunc the index value in the virtual function table is constant (set to 1)
③ at compile time, the compiler cannot know the specific object, but it can implement a function call based on a virtual function table in the base Sub-object of the object that the pointer p points to (that is, the portion of memory that the child class and the parent overlap). The compiler might then modify the code of the virtual function call to the following pseudo-code:
(*p->vptr[1// assume that the Vfunc function has an index value of 1 in the Virtual function table,// parameter p is the this pointer, Because member functions pass through the this pointer by default.
(3) Realize polymorphism:
① if P points to a base object, it calls a function in the virtual function table of the parent class base itself that has an index value of 1.
② if P points to a base derived class object, it invokes a function in the virtual function table in the subclass itself that has an index value of 1, which enables polymorphism. (Note that the virtual function tables of the parent and child classes are independent of each other, except that the subclasses copy a portion of the parent class.)
③ This function call is implemented according to the virtual function table of the object referred to by pointer P, at compile time because the real object referred to by pointer P cannot be determined, it is not possible to determine which function is actually called, but is determined dynamically at run time according to the object referred to in pointer p. Therefore, virtual functions are dynamically bound at run time , not statically at compile time .
(4) Summary
① when a virtual function is declared in a class, the compiler generates a virtual function table in the class that is a data structure that stores the address of the member function (virtual function).
The ② virtual function table is automatically generated and maintained by the compiler.
The ③ virtual member function is placed into the virtual function table .
④ There is a virtual function, Each object has a pointer to the virtual function table
Analysis of polymorphic nature of "programming experiment"
5. Summary
(1) The essence of inheritance is the superposition of member variables between father and son
(2) The polymorphism in C + + is realized by the virtual function table
(3) Virtual function table is automatically generated and maintained by the compiler
(4) The call efficiency of virtual function is lower than ordinary member function.
"References": detailing the memory layout of C + + objects in the C + + object model
51st Lesson C + + object Model analysis (bottom)