1. Three ways to inherit:
Public inheritance, private inheritance (private), protection Inheritance (protected)
A description of the three inheritance methods, as shown in the following table:
Characteristics |
Public inheritance |
Protect inheritance |
Private inheritance |
Public members become |
Public members of derived classes |
Protected members of derived classes |
Private members of derived classes |
Protect members into |
Protected members of derived classes |
Protected members of derived classes |
Private members of derived classes |
Private members become |
Accessible only through the base class interface |
Accessible only through the base class interface |
Accessible only through the base class interface |
Can I convert implicitly? |
Is |
Is |
Whether |
, &NB Sp , &NB Sp , &NB Sp , &NB Sp , &NB Sp , &NB Sp
2. What is multiple inheritance
When a class has more than one base class, this inheritance is called multiple inheritance.
For example, there are two classes, waiter class waiter, singer Class singer, we have a class is both a waiter and a singer,
Then we can define a multiple-inheritance relationship for the class as follows:
class waiter{}; class singer{}; class Singerwaiter: public Waiter, public singer{};
3. What are the problems with multiple inheritance?
Multiple inheritance is more complex and prone to problems than single inheritance, so we do not recommend using multiple inheritance.
The two main problems with multiple inheritance are:
1) from two different base classes, inherit the same name method
As shown in the following example:
classwaiter{ Public: voidWork () {std::cout<<"Service"<<Std::endl;}};classsinger{ Public: voidWork () {std::cout<<"Sing"<<Std::endl;}};classSingerwaiter: PublicWaiter, Publicsinger{};intMain () {Singerwaiter singerwaiter; Singerwaiter.work (); return 0;}
The compiler does not know which base class's work method to call, so it will report singerwaiter.work ();
2) indirectly inherit multiple instances of the same class from multiple base classes
As shown in the following example:
class worker{}; class Waiter:public worker{}; class Singer:public worker{}; class Singerwaiter:public waiter,public Span style= "color: #000000;" > singer{}; int main () {Singerwaiter singerwaiter; Worker *PW = &singerwaiter; return 0 ;}
Will error worker *PW = &singerWaiter; base class worker is not clear.
This is because the constructors for the waiter class and the singer class are called separately when the Singerwaiter object is created.
The waiter class and the singer class also invoke the constructor of the worker class separately, generating two instances of the worker class,
So the PW pointer does not know which worker instance to point to.
4. How to solve the problems caused by multiple inheritance
for problem one, when we call, we need to explicitly indicate which class to invoke , as follows:
int Main () { singerwaiter singerwaiter; Singerwaiter.waiter::work (); // Methods to invoke the waiter class Singerwaiter.singer::work (); // Methods to invoke the singer class return 0 ;}
for question two, we introduce the concept of virtual base class. is as follows:
class worker{}; class Waiter:virtual worker{}; class Singer:virtual worker{}; class Singerwaiter:public waiter,public Span style= "color: #000000;" > singer{}; int main () {Singerwaiter singerwaiter; Worker *PW = &singerwaiter; return 0 ;}
When we declare a virtual keyword when a subclass inherits, it indicates that the base class worker is a virtual base class .
Waiter Objects and singer objects, which are generated when singerwaiter are instantiated, share a base class worker object.
5. Problems to be aware of using virtual base classes
We know that in an inheritance relationship, the constructor of a class has transitivity, as shown in the following code:
classa{Private: intA; Public: A (intn=0): A (n) {}int Get(){returnA;}};classB: Publica{Private: intb; Public: B (intm=0,intn=0): A (n), B (m) {}int Get(){returnb;}};classC: Publicb{Private: intC; Public: C (intq=0,intm=0,intn=0): B (M,n), C (q) {}int Get(){returnC;} voidShow () {std::cout<<a::Get() <<" "<<b::Get() <<" "<<c::Get() <<Std::endl; }};intMain () {C C (1,2,3); C.show (); return 0;}
The output is: 3 2 1
The constructor for C is called, and the B,a constructor is initialized with the arguments passed in.
Let's look at the case where the virtual base class is used:
classa{Private: intA; Public: A (intn=0): A (n) {}int Get(){returnA;}};classB:Virtual Publica{Private: intb; Public: B (intm=0,intn=0): A (n), B (m) {}int Get(){returnb;}};classC: Publicb{Private: intC; Public: C (intq=0,intm=0,intn=0): B (M,n), C (q) {}int Get(){returnC;} voidShow () {std::cout<<a::Get() <<" "<<b::Get() <<" "<<c::Get() <<Std::endl; }};intMain () {C C (1,2,3); C.show (); return 0;}
The output is: 0 2 1
Note A does not initialize with the parameters passed in.
This is because in the virtual base class, we assume that there will be multiple subclasses passing arguments to the virtual base class, in order to avoid this situation,
In the case of virtual base classes, subclass C is forbidden to pass arguments to virtual base class A using intermediate Class B, at which point A's default constructor is called.
So how do we use parameters to initialize the virtual base class?
The answer is that we can initialize the constructor of the virtual base class A directly in subclass C, as shown in the following code:
classa{Private: intA; Public: A (intn=0): A (n) {}int Get(){returnA;}};classB:Virtual Publica{Private: intb; Public: B (intm=0,intn=0): A (n), B (m) {}int Get(){returnb;}};classC: Publicb{Private: intC; Public: C (intq=0,intm=0,intn=0): A (M), B (M,n), C (q) {}int Get(){returnC;} voidShow () {std::cout<<a::Get() <<" "<<b::Get() <<" "<<c::Get() <<Std::endl; }};intMain () {C C (1,2,3); C.show (); return 0;}
The output is: 3 2 1
Skip the Intermediate class and call the constructor of the base class directly, which is only suitable for virtual base classes.
"Indirect non-virtual base class not allowed" is an error in non-virtual base class.
Reference: "C + + primer.plus" pp.551-567
C + + Multiple inheritance