In the example mentioned in "Multi-inheritance", Class A, CLASS B1, Class B2, and class C constitute the hierarchy of class inheritance. In this structure, the object of class C will contain sub-objects of Two Classes. Because Class A is a public base class on the two inheritance paths of the derived class C, this public base class will generate multiple base class sub-objects in the object of the derived class. If you want this public base class to generate only one base class sub-object in the derived class, you must set this base class to a virtual base class.
Introduction and description of virtual base classes
The previous section briefly introduced the reasons for introducing the virtual base class. In fact, the real purpose of introducing the virtual base class is to solve the problem of ambiguity.
The description format of the virtual base class is as follows::
Virtual <Inheritance Method> <Base Class Name>
Among them, virtual is the keyword of the virtual class. The description of the virtual base class is written after the name of the derived class when the derived class is defined. For example:
Class { Public: Void F (); Protected: Int; }; Class B: virtual public { Protected: Int B; }; Class C: virtual public { Protected: Int C: }; Class D: Public B, public C { Public: Int g (); PRIVATE: Int D; }; |
Because the virtual base class is used, the relationship between Class A, Class B, Class C and Class D is shown as follows in the Dag graph:
A {f (),}
//
B {B} c {c}
//
D {G (), d}
From this figure, we can see that the virtual base class sub-objects of different inheritance paths are merged into an object. This is the role of the virtual base class, which eliminates the possible ambiguity before merging. In this case, only one class A object exists in the Class D object. Therefore, the following references are correct:
D N;
N. F (); file: // The reference to F () is correct.
Void D: G ()
{
F (); file: // The F () reference is correct.
}
The following sections are correct.
D N;
A * pA;
Pa = & N;
In this example, PA is a pointer to an object of Class A, n is an object of class D, and N is the address of the N object. Pa = & n is the object that points the PA pointer to Class D. This is correct and has no ambiguity.
Constructor of the virtual base class
As mentioned above, in order to initialize the sub-objects of the base class, the constructor of the derived class must call the constructor of the base class. For the virtual base class, because the object of the derived class has only one virtual base class sub-object. To ensure that the virtual base class sub-object is initialized only once, the virtual base class constructor must be called only once. Because the hierarchy of the inheritance structure may be deep, it is required that the class specified when the object is created is called the most derived class. C ++ stipulates that the sub-objects of the virtual base class are initialized by the constructor of the most derived class by calling the constructor of the virtual base class. If a derived class has a direct or indirect virtual base class, the initial list of the constructor members of the derived class must list the calls to the virtual base class 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 call of this virtual base class constructor must be listed in the member initialization list of the constructor In the derived class that is directly or indirectly inherited from the virtual base class. However, only the constructor of the most derived class used to create an object calls the constructor of the virtual base class, the constructor calls to this virtual base class listed in the base class of the derived class are ignored during execution. This ensures that the object of the virtual base class is initialized only once.
C ++ also stipulates that a call to the virtual base class and non-virtual base class constructor will appear in the member initialization list, then, the constructor of the virtual base class is executed before the constructor of the non-virtual base class.
The following example describes how to use constructors of a derived class with a virtual base class.
# Include Class { Public: A (const char * s) {cout <~ A (){} };Class B: virtual public { Public: B (const char * S1, const char * S2): A (S1) { Cout <} }; Class C: virtual public { Public: C (const char * S1, const char * S2): A (S1) { Cout <} }; Class D: Public B, public C { Public: D (const char * S1, const char * S2, const char * S3, const char * S4) : B (S1, S2), C (S1, S3), A (S1) { Cout <} }; Void main () { D * PTR = new D ("Class A", "Class B", "Class C", "Class D "); Delete PTR; } |
The output result of this program is:
Class
Class B
Class C
Class D
The virtual base class is used in the derived classes B and C, so that the created Class D object has only one virtual base class sub-object.
The constructor Class A contains the constructor in the member initialization list of the constructor Class B, C, and D.
When a Class D object is created, only the virtual base class constructor listed in the initialization list of the Class D constructor is called and called only once, the virtual base class constructor listed in the member initialization list of the Class D-based constructor is not executed. This can be seen from the output results of the program.