This tutorial introduces C++'s multiple inheritance capabilities. The tutorial focuses on multiple inheritance syntax. It also demonstrates how to access inherited members of a derived class when those members have the same name in each of the base classes. This tutorial is intended for students and developers who are already familiar with single inheritance in C++. In our subsequent tutorial, Multiple Inheritance and virtual Base Classes, we continue our presentation of multiple inheritance by investigating the so-called diamond inheritance problem.
Download the code examples for this tutorial.
[Note: This tutorial is an excerpt (Section 24.7) of Chapter 24, Other Topics, from our textbook C++ How to Program, 5/e. These tutorials may refer to other chapters or sections of the book that are not included here. Permission Information: Deitel, Harvey M. and Paul J., C++ HOW TO PROGRAM, ©2005, pp.1213-1218. Electronically reproduced by permission of Pearson Education, Inc., Upper Saddle River, New Jersey.]
24.7 Multiple Inheritance (Continued)
The overloaded stream insertion operator (Fig. 24.10, lines 18–23) uses its second parameter—a reference to aDerived object—to display a Derived object’s data. This operator function is a friend of Derived, so operator<< can directly access all of class Derived’s protected and private members, including the protected data member value (inherited from class Base1), protected data member letter (inherited from class Base2) and private data member real (declared in class Derived).
Now let us examine the main function (Fig. 24.11) that tests the classes in Fig. 24.7–Fig. 24.10. Line 13 creates Base1 object base1 and initializes it to the int value 10, then creates the pointer base1Ptr and initializes it to the null pointer (i.e., 0). Line 14 creates Base2 object base2 and initializes it to the char value 'Z', then creates the pointer base2Ptr and initializes it to the null pointer. Line 15 creates Derived object derived and initializes it to contain the int value 7, the char value 'A' and the double value 3.5.
|
||
| Fig. 24.11 | Demonstrating multiple inheritance. | |
Output
Object base1 contains integer 10
Object base2 contains character Z
Object derived contains:
Integer: 7
Character: A
Real number: 3.5
Data members of Derived can be accessed individually:
Integer: 7
Character: A
Real number: 3.5
Derived can be treated as an object of either base class:
base1Ptr->getData() yields 7
base2Ptr->getData() yields A
|
Lines 18–20 display each object’s data values. For objects base1 and base2, we invoke each object’s getData member function. Even though there are two getData functions in this example, the calls are not ambiguous. In line 18, the compiler knows that base1 is an object of class Base1, so class Base1’s version of getData is called. In line 19, the compiler knows that base2 is an object of class Base2 so class Base2’s version of getData is called. Line 20 displays the contents of object derived using the overloaded stream insertion operator.
Resolving Ambiguity Issues That Arise When a Derived Class Inherits Member Functions of the Same Name from Multiple Base Classes
Lines 24–27 output the contents of object derived again by using the get member functions of class Derived. However, there is an ambiguity problem, because this object contains two getData functions, one inherited from class Base1 and one inherited from class Base2. This problem is easy to solve by using the binary scope resolution operator. The expression derived.Base1::getData() gets the value of the variable inherited from class Base1 (i.e., the int variable named value) and derived.Base2::getData() gets the value of the variable inherited from class Base2 (i.e., the char variable named letter). The double value in real is printed without ambiguity with the call derived.getReal()—there are no other member functions with that name in the hierarchy.
Demonstrating the Is-A Relationships in Multiple Inheritance
The is-a relationships of single inheritance also apply in multiple-inheritance relationships. To demonstrate this, line 31 assigns the address of object derived to the Base1 pointer base1Ptr. This is allowed because an object of class Derived is an object of class Base1. Line 32 invokes Base1 member function getData via base1Ptr to obtain the value of only the Base1 part of the object derived. Line 35 assigns the address of object derived to the Base2 pointer base2Ptr. This is allowed because an object of class Derived is an object of class Base2. Line 36 invokes Base2 member function getData via base2Ptr to obtain the value of only the Base2 part of the object derived.
Other tutorials on this topic:
24.7 Multiple Inheritance (You are here).
24.8 Multiple Inheritance and virtual Base Classes

