Wrox Press C++ Tutorial


Multiple Inheritance

All our derived classes so far have had a single direct base class, but we aren't limited to that. In fact, a derived class can have several base classes; this is referred to as multiple inheritance. This means, of course, that multiple indirect bases are also possible.

Multiple Base Classes

It's quite difficult to come up with an example of a class with multiple base classes that is based on relationships in the real world. Defining a class, such as Box, in terms of the class Container reflects the real-world relationship between a box and a container. A box is a form of container, so we are defining a more specific object from a more general one. With most real-world objects, this unidirectional specialization pattern applies. Multiple base classes are often used in practice for the convenience of implementation rather than to reflect any particular relationships between objects.

However, we could consider the example of a Package, which might be a combination of a Container, or some specialized form of container such as a Box, together with the contents of the container defined by a class Contents. We could define the class Package as derived from both the class Box and the class Contents. This could be represented like so:

The definition of the class would look like this:

class Package: public Box, public Contents
{
...
};

The class Package will now inherit all the members of both classes, with the same access specifiers as appear in the definitions of the base classes, since they are defined as public base classes. There is no access to members of the base class declared as private, however; the access limitations for inherited class members, which we discussed earlier in this chapter, apply equally well to classes with multiple bases.

Things can get a little more complicated now. For example, it's conceivable that both base classes could have a public member function, Show(), to display the contents of an object. We could have a statement to call the Show() member function of an object of the Package class, myPackage, like this:

myPackage.Show();

This statement, however, is ambiguous, since the class Package contains two members with the same name, Show(), one inherited from each of the base classes. The compiler has no way of knowing which one should be called, so this will result in an error message. If you need to call one or the other, you have to use the scope resolution operator to specify which of the two functions you want to invoke. For example, you could write this,

myPackage.Contents::Show();

which makes it quite clear that you want to call the function that is inherited from the class Contents.

Virtual Base Classes

A further complication can arise with multiple inheritance if the direct base classes are themselves derived from another class or classes. The possibility arises that both base classes could be derived from a common class. For instance, the classes Contents and Box, which we used in the definition of the class package, could be derived from another base called RockBottom. Their definitions could then be something like this:

class Contents: public RockBottom
{
...
};

class Box: public RockBottom
{
...
};

Now the class Package will contain two copies of the members of the class RockBottom, as illustrated here:

In the class Package, we end up with two data members called x, and two function members Show(). The duplication of the members of the indirect base can at best be confusing, and at worst it can cause a lot of problems. However, it's easy to avoid by simply modifying the definitions of the base classes Box and Contents such that the class RockBottom is specified as a virtual base class. Their definitions in outline would then be as follows:

class Contents: public virtual RockBottom
{
...
};

class Box: public virtual RockBottom
{
...
};

Now there will be only one instance of the members of the base class RockBottom in any class derived from these two classes, and any problems with the original definition of the class Package disappear. Specifying the base class as virtual instructs the compiler to make sure that the data members are not duplicated in a derived class, even where there are multiple occurrences of the class as an indirect base.


© 1998 Wrox Press