Virtual inheritance and virtual base classes actually talk about the same thing, but different books have different expressions. We recommend the virtual inheritance statement here (because someone always asks what the virtual base class is, this can be interpreted as virtual inheritance, a method of inheritance. Some books may want to write an action as a noun, Which is irresponsible ). Virtual inheritance is a special method inherited by C ++ for special purposes. What is the purpose? That is to avoid the ambiguity under the Inheritance Mechanism (ambiguity: the program produces two or more possibilities, making the compiler overwhelmed)
The ambiguity under the Inheritance Mechanism is generally reflected in the two cases. The virtual inheritance to be introduced mainly solves the ambiguity in the second case, let's talk about both cases:
[Scenario 1]: The ambiguity generated by members of multiple base classes with the same name
Class A // define a Class
{
Public:
A () {cout <"A called" <Endl ;}
Void print () {cout <"a print" <Endl ;}
PRIVATE:
};
Class B // define a Class B
{
Public:
B () {cout <"B called" <Endl ;}
Void print () {cout <"B print" <Endl ;}
PRIVATE:
};
Class C: Public A, public B // defines a class C inherited from a, B
{
Public:
C (){}
PRIVATE:
};
Int main (void)
{
C;
C. Print (); --------------------------------------------------------- mark 1
Getchar ();
Return 0;
}
As shown in the Code, the main program generates ambiguity when it executes the mark1 mark. The C object has two base classes, and the compiler does not know the print () of the call to () or print () of B. The solution of this ambiguity has nothing to do with virtual inheritance. It needs to be solved by acting on the symbol, that is, C. print () to C. a: Print (); then the print method of A is called, that is, the base class of the method to be called.
[Case 2]: The ambiguity produced by the common base classes of multiple parent classes
A is the common base class of B and C. D inherits from B and C.
Class
{
Public:
A () {cout <"A called" <Endl ;}
Void print () {cout <"a print" <Endl ;}
PRIVATE:
};
Class B: public
{
Public:
B () {cout <"B called" <Endl ;}
PRIVATE:
};
Class C: public
{
Public:
C () {cout <"C called" <Endl ;}
PRIVATE:
};
Class D: Public B, public C
{
Public:
D () {cout <"d called" <Endl ;}
PRIVATE:
};
Int main (void)
{
D;
D. Print (); --------------------------------------------------------- mark 2
Getchar ();
Return 0;
}
As shown in the Code, the main program generates ambiguity when it executes the mar2 mark. Although only the base class A contains print (), there are two inherited routes, the compiler does not know whether to look up from the B route or from the c direction. The same will cause an error. here we can use the first method to act on the symbol D. print () to D. b: Print () tells the compiler to inherit from B. Of course, you can also change it to D. c: Print (). In addition to this solution, there is another solution: using the virtual Inheritance Mechanism. In fact, the root cause of the above ambiguity is that in this special inheritance mode, the parent class A has two copies with B and C respectively, there is a conflict when calling the copy method. Which copy is called in print? As a result, everyone will think that if there is only one copy, there will be no conflict, and virtual inheritance provides this mechanism. According to the above example, you only need to modify the Inheritance Method of B and C on a, that is, add a keyword virtual
Class B: virtual public
{
Public:
B () {cout <"B called" <Endl ;}
PRIVATE:
};
Class C: virtual public
{
Public:
C () {cout <"C called" <Endl ;}
PRIVATE:
};
This is equivalent to constructing a copy without a Class A. if it already exists, use the existing one. In this way, there is only one copy, the ambiguity is eliminated.
There is not much about virtual inheritance. In the end, there are not many things about inheritance. In fact, there is only one access control and one call order to clarify the two, after figuring out the above, I will talk about one thing below,
In some cases, it is called the rule of inheritance:
A member with the same name in the base class is set in the derived class, that is, the name of the member in the base class is used again in the derived class, and the name of the base class is hidden behind it, all calls are performed on the members of the derived class, unless the domain operator ::.
For example:
[Example 1]
Class
{
Public:
A () {cout <"A called" <Endl ;}
Void print () {cout <"a print" <Endl ;}
PRIVATE:
};
Class B: public
{
Public:
B () {cout <"B called" <Endl ;}
Void print () {cout <"B print" <Endl ;}
PRIVATE:
};
Int main (void)
{
B;
B. Print ();
Getchar ();
Return 0;
}
The print must be "B print". If you want to print "a print", you can only change it to B. A: Print ();
It should be noted that this is not a heavy load of print (it is the same method at all, it does not matter with the heavy load), it should be called "hidden" more appropriate.
[Example 2]
Class
{
Public:
A () {cout <"A called" <Endl ;}
Void print () {cout <"a print" <Endl ;}
PRIVATE:
};
Class B: public
{
Public:
B () {cout <"B called" <Endl ;}
Void print (int A) {cout <"B print" <Endl ;}
PRIVATE:
};
Int main (void)
{
B;
B. Print ();
Getchar ();
Return 0;
}
This example is compiled and failed! How is it possible that the print parameter of B does not meet the requirements, not that the print of the base class meets the requirements? Why not call it? In the original derived class B, the print was changed, this is a heavy load. Many people refer to this as "Overwrite", which is a bit reasonable. So how can I not access print () in Class A? How can I change it unless it uses the scope symbol, add a parameter and a scope operator to see how you want to use it. Here, I just want to explain "Overwrite.