17.3.2 conversion and multiple base classes
In the case of a single base class, the pointer or reference of the derived class can be automatically converted to the pointer or reference of the base class. This is also true for multi-inheritance, the pointer or reference of a derived class can be converted to any pointer or reference of its base class.
In the case of multiple inheritance, it is more likely to encounter ambiguity conversion. The compiler does not try to distinguish between base classes based on the conversion of the derived classes. The conversion takes every base class as good.
Namespace andsoft
{
Namespace Animal
{
Class ZooAnimal {};
Class Endangered {};
Class Bear: public ZooAnimal {};
Class Panda: public Bear, public Endangered {
Public:
Panda (): Bear (), Endangered (){}
};
}
}
Namespace andsoft
{
Namespace Animal
{
Class ZooAnimal {};
Class Endangered {};
Class Bear: public ZooAnimal {};
Class Panda: public Bear, public Endangered {
Public:
Panda (): Bear (), Endangered (){}
};
}
}
Using namespace randsoft: Animal;
Int _ tmain (int argc, _ TCHAR * argv [])
{
ZooAnimal * za = new Panda ();
Endangered ea = Panda ();
Panda pa = Panda ();
Bear & ba = pa;
Return 0;
}
Using namespace randsoft: Animal;
Int _ tmain (int argc, _ TCHAR * argv [])
{
ZooAnimal * za = new Panda ();
Endangered ea = Panda ();
Panda pa = Panda ();
Bear & ba = pa;
Return 0;
}
1. virtual functions under multiple inheritance
2. Search Based on pointer type or reference type
Like a single inheritance, the pointer or reference of a base class can only access the Members defined (or inherited) in the base class, and cannot access the Members introduced in the derived class.
When a class inherits from multiple base classes, there is no implicit relationship between the base classes and one base class pointer is not allowed to access members of other base classes.
3. Determine which destructor to use
Assuming that all the underlying classes properly define their destructor as virtual functions, no matter which pointer type is used to delete objects, the processing of virtual destructor is consistent.
Assuming that each of these pointers points to a subclass object, the same sequence of destructor calls occurs in each case. The order of destructor calls is the reverse order of the constructor order.
ZooAnimal * za = new Panda ();
Delete za; // execute ~ Panda-> ~ Endangered-> ~ Bear
ZooAnimal * za = new Panda ();
Delete za; // execute ~ Panda-> ~ Endangered-> ~ Bear17.3.3 multi-inherit the replication control of derived classes
The initialization, assignment, and structure of multiple inherited Derived classes are the same as those under a single inheritance, use the base class's own copy constructor, value assignment operator, or destructor to implicitly construct, assign values, or revoke each base class.
The behavior of the combined value assignment operator is similar to that of the copy constructor.
The composite destructor removes every member of the subclass object and calls the Destructor Based on the reverse order of the constructor.
As in the case of single inheritance, if a class with multiple base classes defines its own destructor, The Destructor is only responsible for clearing the derived classes. If the derived class defines its own copy constructor or value assignment operator, the class is responsible for copying (assigning values) All the base class sub-parts. The base class part is automatically copied or assigned only when the derived class uses the combined version of the copy constructor or value assignment operator.
17.3.4 class scopes under multiple inheritance
When a class has multiple base classes, you can use all the direct base classes for simultaneous name search. A multi-inheritance derived class may inherit members of the same name from two or more base classes. The use of this Member is not limited.
1. Multiple Base classes may lead to ambiguity.
2. First, name search occurs.
An error occurs even if two inherited functions have different parameter tables. Similarly, even if a function is private in one class and is public or protected in another class, it is also incorrect.
3. Avoid user-level Ambiguity
You can solve the ambiguity by specifying which class to use.
The best way to avoid potential ambiguity is to define a function version in a derived class that solves the ambiguity.
Namespace andsoft
{
Namespace Animal
{
Class ZooAnimal {
Public:
Void Print (){}
};
Class Endangered {
Public:
Void Print (){}
};
Class Bear: public ZooAnimal {
Public:
Void Print (){
ZooAnimal: Print ();
}
};
Class Panda: public Bear, public Endangered {
Public:
Panda (): Bear (), Endangered (){}
Void Print (){
Bear: Print ();
Endangered: Print ();
}
};
}
}
Namespace andsoft
{
Namespace Animal
{
Class ZooAnimal {
Public:
Void Print (){}
};
Class Endangered {
Public:
Void Print (){}
};
Class Bear: public ZooAnimal {
Public:
Void Print (){
ZooAnimal: Print ();
}
};
Class Panda: public Bear, public Endangered {
Public:
Panda (): Bear (), Endangered (){}
Void Print (){
Bear: Print ();
Endangered: Print ();
}
};
}
} Panda * za = new Panda ();
Za-> Endangered: Print ();
Za-> Print ();
From xufei96's column