䊐 Multiple Identical Base ClassesWhen multiply-derived classes are defined, a direct base class cannot be inherited more than once.. 䊐 IssuesYou will not normally want a class created by
Trang 1A class can contain not just one but several different base classes In this case the class is
derived from multiple base classes in a process known as multiple inheritance.
䊐 The Multiply-Derived Class MotorHome
This class Caris used to represent vehicles and the class Homecontains characteristic values for an apartment, such as floor space, number and type of rooms, and typical oper-ations, such as building, selling, or renting
Using these two classes you can then derive the MotorHomeclass The opposite page shows the inheritance and definition schemes for the new class An object of the
MotorHomeclass contains both the members of Carand the members of Home More specifically, the object contains two base sub-objects of type CarandHome
䊐 Accessibility of Base Classes
Since the MotorHomeclass has two publicbase classes, it assumes the public inter-faces of both classes A MotorHometype object not only allows access to the additional
publicmembers but to all the publicmembers of the base classes CarandHome When defining a multiply-derived class, the accessibility, private,protected, or
public, must be defined separately for each base class The MotorHome class could have the publicbase class Carand the protectedbase class Home
Example: class MotorHome:public Car,protected Home
{ };
If the keyword is omitted, the base class will default to private
Example: class MotorHome : public Car, Home
{ };
This statement defines the publicbase class Carand the privatebase class Home This makes all the publicmembers in Home privatemembers of the derived class
In multiple inheritance each publicbase class establishes an is relationship This is
similar to simple inheritance If the MotorHomeclass inherits two publicbase classes,
a motor-home is a special kind of motor vehicle and a special kind of home.
Trang 2590 C H A P T E R 2 7 M U L T I P L E I N H E R I T A N C E
SUV
class SUV : public PassCar, public Van {
// Here are additional methods and data members };
■ MULTIPLE INDIRECT BASE CLASSES
The multiple indirect base class Car
Definition scheme of class SUV
Trang 3䊐 Multiple Identical Base Classes
When multiply-derived classes are defined, a direct base class cannot be inherited more than once The following statement
Example: class B : public A, public A // Error
{ };
causes the compiler to issue an error message
A class can be derived from several classes that have a common base class, however
This class is then referred to as a multiple indirect base class.
The inheritance graph on the opposite page shows the multiply-derived class SUV, which was derived from the classes PassCarand Van Both base classes were them-selves derived from the Carclass This makes Cara multiple indirect base class of the
SUVclass
䊐 Ambiguity
An object of the SUVclass thus contains the members of Cartwice Access to members
of the Carclass results in ambiguity.
Example: SUV mySUV( .);
cout << mySUV.getProd(); // Error
Both the base classes PassCar andVancontain a method called getProd(), which they both inherited from the Carclass In this case the compiler cannot decide which method is meant
Ambiguity in the context of multiple inheritance is also possible when several base
classes contain members with identical names If both the Homeclass and the Carclass contain a method called getNr(), the getNr()method cannot be correctly identified
in the following statement
Example: MotorHome motorHome( );
motorHome.getNr();
To resolve ambiguity of this kind, you can use the scope resolution operator to determine which base class is meant
Example: cout << motorHome.Home::getNr();
cout << mySUV.PassCar::getProd();
The getNr() method in the Home class is called first, followed by the getProd()
method inherited by PassCarfrom the Carclass
Trang 4592 C H A P T E R 2 7 M U L T I P L E I N H E R I T A N C E
Car
SUV
class PassCar : public virtual Car {
// Here are additional members // of class PassCar
};
class Van : public virtual Car {
// Here are additional members // of class Van
};
■ VIRTUAL BASE CLASSES
The virtual base class Car
Definition scheme
Trang 5䊐 Issues
You will not normally want a class created by multiple inheritance to contain multiple instances of an indirect base class Why should a station wagon contain two versions of the manufacturer’s name or the chassis number for example? So you might be asking yourself whether you can define multiply-derived classes that will contain only one instance of an indirect base class
C++ uses virtual base classes to do this An object in a multiply-derived class contains
only one instance of the members in a virtual base class The inheritance graph on the opposite page uses the SUVclass to illustrate this situation
䊐 Declaration
A direct base class is declared virtual when a derived class is defined You can use the
virtualkeyword, which directly precedes the name of the base class
In the definition scheme shown opposite, the Carclass becomes the virtual base class
ofPassCarandVan However, the fact that the base class Caris virtual has no signifi-cance at this point
A virtual base class takes effect in cases of multiple inheritance The following defi-nition
Example: class SUV
: public PassCar, public Van
{ };
ensures that the SUVclass only contains one instance of the virtual base class Car An object my of the SUV class gets sufficient memory for only one Car class sub-object More specifically, the statement
Example: cout<<"Producer: " << mySUV.getProd();
does not cause ambiguity
The following items are important with respect to virtual base classes:
■ a virtual base class stays virtual even if further derivations are built Each class derived from PassCaralso has the Carclass as a virtual base class
■ you cannot change the declaration of an indirect base class to virtual
You must therefore decide what classes are to be declared virtual when you design the class hierarchy Later modifications will require modifications to the source code of any derived classes
Trang 6594 C H A P T E R 2 7 M U L T I P L E I N H E R I T A N C E
MultiDerived
class multiDerived : public Base1, public Base2,
public Base3 {
// Here are additional data members and methods };
■ CONSTRUCTOR CALLS
䊐 Building an inheritance graph
Class Definition
Inheritance graph
Trang 7䊐 Initialization
When an object is created in a simply-derived class, the sub-objects of the base classes are created first on all levels of the class hierarchy The sub-object whose class is nearer
to the top of the inheritance graph is created first
The order of the constructor calls is “top down” and follows the inheritance graph The activation order used for the constructors in simple inheritance has been generalized for multiple inheritance
䊐 Inheritance Graph
Again, the inheritance graph, also called sub-object lattice, has an important job to do.
When a derived class is defined, the following rules apply:
■ In cases of multiple inheritance, base classes are entered into the inheritance graph from left to right in the order in which they were stated when the class was defined The graph opposite illustrates this point
If the class hierarchy does not contain any virtual base classes, the following applies to the activation order of the constructors
■ The base class constructors are executed first, top-down and from left to right on each level
■ Finally, the constructor belonging to the current class, which is at the bottom of the inheritance graph, is executed
If we look at the example on the opposite page, this means that the sub-objects of the base classes Base1,Base2, and Base3are created in this order Then the constructor
ofMultiDerivedis executed
䊐 Base Initializers
The constructor for the class at the bottom end of the inheritance graph uses base initial-izers to pass the values to the direct and indirect base classes If the base initializer defini-tion is missing in a constructor definidefini-tion, the default constructor of the base class is automatically executed
Initial values are thus passed to the base class constructors “bottom up.”
Trang 8596 C H A P T E R 2 7 M U L T I P L E I N H E R I T A N C E
class SUV : public PassCar, public Van {
private:
// public:
SUV( ) : Car( ) {
// Initialize additional data members }
void display() const {
PassCar::display();
Van::display();
// Output additional data members }
};
■ INITIALIZING VIRTUAL BASE CLASSES
Class SUV
Trang 9䊐 Constructor Calls in Virtual Base Classes
When an object is created for a multiply-derived class, the constructors of the base classes are called first However, if there is one virtual base class in the class hierarchy,
the virtual base class constructor is executed before a constructor of a non-virtual base
class is called
The constructors of the virtual base classes are called first, followed by the constructors of non-virtual base classes in the order defined in the inheritance graph
The constructor of a virtual base class is called with the arguments stated for the base initializer of the
last class to be derived, i.e class at the bottom end of the inheritance graph.
The constructor of the virtual base class nearest the top of the inheritance graph is executed first This does not necessarily mean the top level of the class hierarchy, since a virtual base class can be derived from a non-virtual base class
In our example with the multiply-derived class SUV(Sport Utility Vehicle) the con-structor for the virtual base class Caris called first, followed by the direct base classes
PassCarandVan, and last but not least, the constructor of the SUVclass
䊐 Base Initializers
You may be wondering what arguments are used to call the constructor of a virtual base class A base initializer of the directly-derived class or any other derivation could be responsible The following applies:
The example opposite shows SUVcontaining a constructor with one base initializer.
Its arguments are passed to the constructor of the virtual base class Car For the purpose of initialization, it does not matter whether a class derived directly from Car contains a base initializer or not Base initializers for virtual indirect base classes defined in the constructor of a direct base class are ignored If the base classes
PassCarandVanalso contained base initializers for the virtual base class Car, these would be ignored too
If the constructor for the last derived class does not contain a base initializer, the default constructor is executed for each virtual base class Whatever happens, a default constructor must then exist in every virtual base class! Thus, base initializers that happen
to exist in base classes are also ignored
Trang 10598 C H A P T E R 2 7 M U L T I P L E I N H E R I T A N C E
Data member: Type
Methods:
MotorHome(CATEGORY, long, const string&, int, double );
void setCategory(CATEGORY ) CATEGORY getCategory() const ;
void display() const;
MotorHome
■ EXERCISES
The multiply-derived class MotorHome
Additional members of class MotorHome