# Include <iostream> using namespace STD; Class furniture {public: Furniture (INT nweight) {m_nweight = nweight; cout <"furniture construction" <Endl ;} int m_nweight;}; // virtual inheritance // make the derived class object have only one copy of the basic class (furniture) // In the diamond inheritance, in the following two inheritance relationships, add the virtual inheritance class Safa: virtual public furniture {public: SAFA (INT nweight): Furniture (nweight) {cout <"" <Endl;} void SIT () {}}; class bed: virtual public furniture {public: bed (INT nweight): Furniture (nweight) {cout <"" <Endl ;} void sleep () {}}; // construct the sequence. First, the virtual base class // then the non-virtual base class. Then, the class safabed: public bed is constructed in the declared order, public Safa {public: // pay attention to the construction order of Safa and bed, in the declared order, not the initialization list order safabed (INT nweight): SAFA (nweight), bed (nweight ), furniture (nweight) {bed: m_nweight = nweight; cout <"sofa bed construction" <Endl ;}; int main (INT argc, char * argv []) {safabed thesafabed (100); furniture * pfurniture = (bed *) & thesafabed; thesafabed. sit (); thesafabed. sleep (); cout <sizeof (thesafabed) <Endl; getchar (); Return 0 ;}
Running result:
Note that in the safabed member initialization listInitialize the virtual base class explicitlyFurniture.
If you remove the two virtual attributes when defining the bed and Safa classes, you must also modify the safabed member initialization list and delete the furniture initialization. Otherwise, the compiler prompts: access to "Furniture" is unclear.
The running result is:
Detailed analysis:
Virtual inheritance introduces the inheritance of virtual base classes. The purpose of introducing a virtual base class is to solve the problem of ambiguity arising from the class inheritance process. This ambiguity problem is common in class inheritance systems with diamond inheritance relationships. For example, there are four classes: A, B, C, and D. the inheritance relationship between them is: B inherits a, c inherits a, d inherits B and C. This forms a diamond inheritance relationship. A graph with this inheritance relationship is called a directed acyclic graph. Then Class D has two inheritance paths: d --> B --> A and D --> C -->. Class A is derived from Class D.Public base classes on two inheritance pathsThen, this public base class will generate multiple base class sub-objects in the object of the derived class D. When the base class A member is referenced in D, it will produce obvious ambiguity. To solve this ambiguity, you must set this base class A as a virtual base class.
class A:{ public: void fun(); protected: int a;};class B: virtual public A{ protected: int b;};class C: virtual pulic A{ protected: int c;};class D: public B, public C{ public: int g(); protected: int d;};
In this way, the virtual base class sub-objects in different inheritance paths are merged into child objects in the derived class. This is the role of the virtual base class. In this way, we can eliminate the problem of ambiguity before merging. At this time, only one sub-object of Class A exists in the object of the derived class D. The ambiguity check in C ++ is performed before the access permission or type check.
After the virtual base class is introduced, only one sub-object of the virtual base class exists in the object of the derived class (subclass. When a class has a virtual base class, the compilation system defines a pointer member for the Class Object and points it to the sub-object of the virtual base class. This pointer is calledVirtual base pointer. This concept is different from the virtual function table pointer. In memory, generally, the virtual base class sub-object is placed at the end of the memory block occupied by the derived class object in the derived class object, but this is determined by the compiler.
Constructor of the virtual base class
To initialize sub-objects of the virtual base class, the constructor of the derived class must call the constructor of the base class. Because the object of the derived class has only one virtual base class sub-object, you must ensure that the sub-object of the virtual base class is initialized only once. That is to say, the constructor of the virtual base class can only be called once.
Because the hierarchy of inheritance may be deep, C ++ stipulates that the class when an object is actually created is calledMost derived classThe virtual base class sub-object is the constructor of the most derived class. In its member initialization list, the constructor of the virtual base class is called directly for initialization. If a derived class has a direct or indirect virtual base class, the member initialization list of the constructor of the derived class must list explicit calls to the virtual base class Constructor (unless the virtual base class has a default constructor ). If not listed, it indicates that the default constructor of the virtual base class is used to initialize the virtual base class sub-objects in the object of the derived class.
The member initialization list of the derived class that is directly or indirectly inherited from the virtual base class must list calls to the virtual base class constructor. However, only the constructor of the most derived class that is used to create an object can actually call the constructor of the virtual base class. During initialization of the intermediate classes from the most derived class to the virtual base class, the calls to the constructors listed by them to the virtual base class are ignored during actual execution. This ensures that the sub-objects of the virtual base class are initialized only once.
C ++ also stipulates that: when a call to the virtual base class and non-virtual base class constructor occurs simultaneously in the member initialization list, the constructor of the virtual base class is executed before the constructor of the non-virtual base class.
When a virtual base class is required, the initialization list of each inheritance class must contain statements that initialize the virtual base class. These initialization statements are actually called only in the bottom-layer subclass (the most derived class), so that the status of the virtual base class sub-objects obtained by some upper-layer sub-classes is not as expected, the initialization statement is skipped. Therefore, it is generally recommended that you do not include any data members in the virtual base class, that is, do not have a status, but can only be used as an interface class.
The Reference Links for memory layout are available, but I do not understand it.
Reference: http://bdxnote.blog.163.com/blog/static/844423520091130112659501/