C ++ multi-Inheritance
Multi-inheritance can be seen as an extension of single inheritance. Multi-inheritance means that a derived class has multiple base classes. The relationship between the derived class and each base class can still be considered as a single inheritance.
The Definition Format of the derived class under multiple inheritance is as follows:
Class <derived class name>: <Inheritance Method 1> <base class name 1>, <Inheritance Method 2> <base class name 2> ,...
{
<Derived class body>
};
Where, <Inheritance Method 1>, <Inheritance Method 2> ,... Is one of three inheritance Methods: public, private, and protected. For example:
Class { ... }; Class B { ... }; Class C: Public A, public, B { ... }; |
The derived class C has two base classes (Class A and Class B). Therefore, Class C is multi-inherited. According to the inheritance rules, the member of the derived class C contains the member of the base class B and the member of the class itself.
Multi-inherited Constructor
In the case of multi-inheritance, the constructor format of the derived class is as follows:
<Derived class name> (<total parameter table>): <base class name 1> (<parameter table 1>), <base class name 2> (<parameter table 2> ),...
<Sub-Object Name> (<parameter table n + 1> ),...
{
<Derived class constructor>
}
The parameters in the <Total Parameter List> contain the following parameter lists.
The constructor of a Multi-inherited derived class is similar to a single-inherited derived class constructor. It must call all the base class constructor of the derived class at the same time. At the same time, the number of parameters of the derived class must contain the number of parameters required to complete the initialization of all base classes.
The execution sequence of the derived class constructor is to first execute the constructor of the base class and then execute the constructor of the derived class, the execution sequence of each base class constructor at the same level depends on the sequence of the base classes specified when the derived class is defined, and is irrelevant to the sequence of the member initialization list defined in the derived class constructor. That is to say, the execution sequence of the base class constructor depends on the sequence of the base class when the derived class is defined. It can be seen that the order of the members in the initialization list of the derived class constructor can be arbitrarily arranged.
The following example describes the composition and execution sequence of the derived class constructor.
# Include Class B1 { Public: B1 (int I) { B1 = I; Cout <"constructor B1 ."} Void print (){} PRIVATE: Int B1; }; Class B2 { Public: B2 (int I) { B2 = I; Cout <"constructor B2 ."} Void print (){} PRIVATE: Int B2; }; Class B3 { Public: B3 (int I) { B3 = I; Cout <"constructor B3 ." } Int getb3 () {return B3 ;} PRIVATE: Int B3; }; Class A: Public B2, public B1 { Public: A (int I, Int J, int K, int L): B1 (I), B2 (J), BB (k) { A = L; Cout <"constructor ."} Void print () { B1: Print (); B2: Print (); } PRIVATE: Int; B3 BB; }; Void main () { A aa (1, 2, 3, 4 ); AA. Print (); } |
The output result of this program is:
Constructor b2.2
Constructor b1.1
Constructor b3.3
Constructor A.4
1
2
4, 3
In this program, the scope OPERATOR: is used to solve the scope conflict problem. In the definition of the print () function in the derived class A, the B1: Print; and B2: Print () statements are used to specify the print () function of the class to be called, respectively, this usage should be learned.
Ambiguity
Generally, the access to the base class members in the derived class should be unique. However, due to the multi-inheritance, the access to a member in the base class may not be unique, this is called the ambiguity of access to base class members.
In fact, this problem has already occurred in the above example. In the above example, both the base classes B1 and B2 of the derived class a have a member function print (). Which base class is used to access the print () function in a derived class? As a result, there is a ambiguity. However, this problem is solved in the preceding example by using the scope OPERATOR. If this parameter is not specified, the problem of ambiguity occurs.
The following is a simple example to illustrate the problem of ambiguity. For example:
Class { Public: Void F (); };Class B { Public: Void F (); Void g (); }; Class C: Public A, public B { Public: Void g (); Void H (); }; |
If you define a class C object C1:
C C1;
Access to function f ()
C1.f ();
It has two meanings: Is F () in category A, or F () in category B?
The solution can eliminate ambiguity by using the previously used member name limitation, for example:
C1.a: F ();
Or
C1. B: F ();
However, the best solution is to define a member with the same name f () in Class C, and then call A: F () according to your needs (), b: F () or both. In this way, c1.f () calls C: F ().
Similarly, F () is called by the member functions in Class C. For example:
Viod C: H ()
{
F ();
}
Here there are two meanings. This function should be modified:
Void C: H ()
{
A: F ();
}
Or
Void C: H ()
{
B: F ();
}
Or
Void C: F ()
{
A: F ();
B: F ();
}
In addition, in struct, Class B has a member function g (), and class C also has a member function g (). At this time,
C1.g ();
There is no ambiguity. It refers to C: G (), not B: G (). Because the two G () functions appear in the base class B and the other in the C class, the members of the derived class will control the same name members in the base class. Therefore, in the above example, g () in Class C controls g () in Class B, which does not have ambiguity. You can select the name of the supporter.
When a derived class is derived from multiple base classes, and these base classes have a common base class, access the members described in the base class, it may also have ambiguity. For example:
Class { Public: Int; }; Class B1: public { PRIVATE: Int B1; }; Class B2: public { PRIVATE: Int B2; }; Class C: Public B1, public B2 { Public: Int F (); PRIVATE: Int C; }; |
Known: C C1;
The following two accesses have their meanings:
C1.a;
C1.a:;
The following two accesses are correct:
C1.b1:;
C1.b2:;
The member function f () of Class C can eliminate ambiguity with the following definition:
Int C: F ()
{
Retrun B1: A + B2:;
}
Due to the ambiguity, a class cannot be inherited from the same class more than once. For example:
Class A: Public B, public B
{
...
}
This is incorrect.