In this chapter, you’ll look at a topic that lies at the heart of object-oriented programming: inheritance. Inheritance is the means by which you can create new classes by reusing and expanding on existing class definitions. Inheritance is also fundamental to making polymorphism possible. We’ll discuss polymorphism in the next chapter, so what you’ll learn there is an integral part of what inheritance is all about. There are subtleties in inheritance that we’ll tease out using code that shows what is happening.
How inheritance fits into the idea of object-oriented programming
What base classes and derived classes are and how they’re related
How to define a new class in terms of an existing class
The use of the protected keyword as an access specification for class members
How constructors behave in a derived class and what happens when they’re called
What happens with destructors in a class hierarchy
The use of using declarations within a class definition
What multiple inheritance is
How to convert between types in a class hierarchy
Classes and Object-Oriented Programming
We’ll begin by reviewing what you’ve learned so far about classes and explain how that leads to the ideas we’ll introduce in this chapter. In Chapter 11, we explained the concept of a class and that a class is a type that you define to suit your own application requirements. In Chapter 12 you learned how you can overload the basic operators so that they work with objects of your class types. The first step in applying object-oriented programming to solve a problem is to identify the types of entities to which the problem relates and to determine the characteristics for each type and the operations that will be needed to solve the problem. Then you can define the classes and their operations, which will provide what you need to program the solution to the problem in terms of instances of the classes.
Any type of entity can be represented by a class—from the completely abstract such as the mathematical concept of a complex number to something as decidedly physical as a tree or a truck. A class definition characterizes a set of entities, which share a common set of properties. So, as well as being a data type, a class can also be a definition of a set of real-world objects, or at least an approximation that is sufficient for solving a given problem.
In many real-world problems, the types of the entities involved are related. For example, a dog is a special kind of animal. A dog has all the properties of an animal plus a few more that characterize a dog. Consequently, classes that define the Animal and Dog types should be related in some way. As a dog is a specialized kind of animal, you can say that any Dog is also an Animal. You would expect the class definitions to reflect this. A different sort relationship is illustrated by an automobile and an engine. You can’t say that an Automobile is an Engine, or vice versa. What you can say is that an Automobile has an Engine. In this chapter you’ll see how the is a and has a relationships are expressed by classes.
Hierarchies
In previous chapters, we defined the Box class to represent a rectilinear box. The defining properties of a Box object were just the three orthogonal dimensions. You can apply this basic definition to the many different kinds of rectangular boxes that you find in the real world: cardboard cartons, wooden crates, candy boxes, cereal boxes, and so on. All these have three orthogonal dimensions, and in this way they’re just like generic Box objects. However, each of them has other properties such as the things they’re designed to hold, the material from which they’re made, or the labels printed on them. You could describe them as specialized kinds of Box objects.

Classes in a hierarchy
The Carton class is an extension of the Box class. You might say that the Carton class is derived from the Box class. In a similar way, the FoodCarton class has been derived from the Carton class. It’s common to indicate this relationship diagrammatically by using an arrow pointing toward the more general class in the hierarchy. This notation is used also by the Unified Modeling Language (UML), the de facto standard way for visualizing the design of object-oriented software programs. Figure 13-1 is a simplified UML class diagram, with some additional annotations to clarify.
In specifying one class in terms of another, you’re developing a hierarchy of interrelated classes. One class is derived from another by adding extra properties—in other words, by specialization—making the new class a specialized version of the more general class. In Figure 13-1, each class in the hierarchy has all the properties of the Box class, which illustrates precisely the mechanism of class inheritance. You could define the Box, Carton, and FoodCarton classes quite independently of each other, but by defining them as related classes, you gain a tremendous amount. Let’s look at how this works in practice.
Inheritance in Classes
To begin with, we’ll introduce the terminology that is used for related classes. Given a class A, suppose you create a new class B that is a specialized version of A. Class A is the base class, and class B is the derived class. You can think of A as being the “parent” and B as being the “child.” A base class is sometimes referred to as a superclass of a class that is derived from it, and the derived class is a subclass of its base. A derived class automatically contains all the member variables of its base class and (with some restrictions that we’ll discuss) all the member functions. A derived class inherits the member variables and member functions of its base class.

Derived class members inherited from a base class
As you can see, the derived class has a complete set of member variables and functions from the base class, plus its own member variables and functions. Thus, each derived class object contains a complete base class subobject, plus its own members.
Inheritance vs. Aggregation
Class inheritance isn’t just a means of getting members of one class to appear in another. There’s an important idea that underpins the whole concept: derived class objects should be sensible specializations of base class objects. To decide whether this is the case in a specific instance, you can apply the is a test, which is that any derived class object is a base class object. In other words, a derived class should define a subset of the objects that are represented by the base class. We explained earlier that a Dog class might be derived from an Animal class because a dog is an animal; more precisely, a Dog object is a reasonable representation of a particular kind of Animal object. On the other hand, a Table class shouldn’t be derived from the Dog class. Although Table and Dog objects share a common attribute in that they both usually have four legs, a Table object can’t really be considered to be a Dog in any way, or vice versa.
The is a test is an excellent first check, but it’s not infallible. For example, suppose you define a Bird class that among other things reflects the fact that most birds can fly. Now, an ostrich is a bird, but it’s nonsense to derive a class Ostrich from the Bird class because ostriches can’t fly! The problem arises because of a poor definition for Bird objects. You really need a base class that doesn’t have the ability to fly as a property. You can then derive two subclasses, one for birds that can fly and the other for birds that can’t. If your classes pass the is a test, you should double-check by asking whether there is anything we can say about (or demand of) the base class that’s inapplicable to the derived class. If there is, then the derivation probably isn’t sound. Deriving Dog from Animal is sensible, but deriving Ostrich from Bird as we described it, isn’t.
If classes fail the is a test, then you probably shouldn’t use class derivation. In this case, you could check the has a test. A class object passes the has a test if it contains an instance of another class. You can accommodate this by including an object of the second class as a member variable of the first. The Automobile and Engine classes that we mentioned earlier are an example. An Automobile object would have an Engine object as a member variable; it may well have other major subassemblies as member variables of types such as Transmission and Differential. This type of relationship is called aggregation .
If the child object contained in a parent object cannot exist independently of its parent, their relation is called composition instead of aggregation. An example of composition would be the relation between a House and a Room, if Rooms cannot exist without a House. If you delete a House, all its Rooms are typically deleted as well. An example of aggregation is the relation Class–Student. Students generally do not cease to exist if their Class is cancelled.
Of course, what is appropriate to include in the definition of a class depends on the application. Sometimes, class derivation is used simply to assemble a set of capabilities so that the derived class is an envelope for packaging a given set of functions. Even then, the derived class generally represents a set of functions that are related in some way. Let’s see what the code to derive one class from another looks like.
Deriving Classes
Here’s a simplified version of the Box class from Chapter 12:
We can define a Carton class based on the Box class. A Carton object will be similar to a Box object but with an extra member variable that indicates the material from which it’s made. We’ll define Carton as a derived class, using the Box class as the base class:
The #include directive for the Box class definition is necessary because it is the base class for Carton. The first line of the Carton class definition indicates that Carton is derived from Box. The base class name follows a colon that separates it from the derived class name, Carton in this case. The public keyword is a base class access specifier that determines how the members of Box can be accessed from within the Carton class. We’ll discuss this further in a moment.
In all other respects, the Carton class definition looks like any other. It contains a new member, material, which is initialized by the constructor. The constructor defines a default value for the string describing the material of a Carton object so that this is also the no-arg constructor for the Carton class. Carton objects contain all the member variables of the base class, Box, plus the additional member variable, material. Because they inherit all the characteristics of a Box object, Carton objects are also Box objects. There’s a glaring inadequacy in the Carton class in that it doesn’t have a constructor defined that permits the values of inherited members to be set, but we’ll return to that later. Let’s first see how these class definitions work in an example:
We get the following output:
The main() function creates a Box object and two Carton objects and outputs the number of bytes occupied by each object. The output shows what you would expect—that a Carton object is larger than a Box object. A Box object has three member variables of type double; each of these occupies 8 bytes on nearly every machine, so that’s 24 bytes in all. Both of the Carton objects are the same size: 56 bytes. The additional memory occupied by each Carton object is down to the member variable material, so it’s the size of a string object that contains the description of the material. The output of the volumes for the Carton objects shows that the volume() function is indeed inherited in the Carton class and that the dimensions have the default values of 1.0. The next statement shows that the accessor functions are inherited too and can be called for a derived class object.
Uncommenting either of the last two statements results in an error message from the compiler. The member variables that are inherited by the Carton class were private in the base class, and they are still private in the derived class, Carton, so they cannot be accessed from outside the class. There’s more, though. Try adding this function to the Carton class definition as a public member:
This won’t compile. The reason is that although the member variables of Box are inherited, they are inherited as private members of the Box class. The private access specifier determines that members are totally private to the class. Not only can they not be accessed from outside the Box class, they also cannot be accessed from inside a class that inherits them.
Access to inherited members of a derived class object is not only determined by their access specification in the base class but by both the access specifier in the base class and the access specifier of the base class in the derived class. We’ll go into that a bit more next.
protected Members of a Class
The private members of a base class being only accessible to member functions of the base class can be, to say the least, inconvenient. Often you want the members of a base class to be accessible from within the derived class but nonetheless protected from outside interference. In addition to the public and private access specifiers for class members, you can declare members as protected. Within the class, the protected keyword has the same effect as the private keyword. protected members cannot be accessed from outside the class except from functions that have been specified as friend functions. Things change in a derived class, though. Members of a base class that are declared as protected are freely accessible in member functions of a derived class, whereas the private members of the base class are not.
We can modify the Box class to have protected member variables:
Now the member variables of Box are still effectively private in that they can’t be accessed by ordinary global functions, but they’re now accessible within member functions of a derived class. If you now try compiling Carton with the carton_volume() member uncommented and the Box class members specified as protected, you’ll find that it compiles without a problem.
Tip
Member variables should normally always be private. The previous example was just to indicate what is possible. In general, protected member variables introduce similar issues as public member variables, only to a lesser extent. We’ll explore this in more detail in the next section.
The Access Level of Inherited Class Members
In the Carton class definition, we specified the Box base class as public using the following syntax: class Carton : public Box. In general, there are three possibilities for the base class access specifier: public, protected, or private. If you omit the base class access specifier in a class definition, the default is private (in a struct definition, the default is public). For example, if you omit the specifier altogether by writing class Carton : Box at the top of the Carton class definition in Ex13_01, then the private access specifier for Box is assumed. You already know that the access specifiers for class members come in three flavors as well. Again, the choice is the same: public, protected, or private. The base class access specifier affects the access status of the inherited members in a derived class. There are nine possible combinations. We’ll cover all possible combinations in the following paragraphs, although the usefulness of some of these will only become apparent in the next chapter when you learn about polymorphism.
First let’s consider how private members of a base class are inherited in a derived class. Regardless of the base class access specifier (public, protected, or private), a private base class member always remains private to the base class. As you have seen, inherited private members are private members of the derived class, so they’re inaccessible outside the derived class. They’re also inaccessible to member functions of the derived class because they’re private to the base class.
- 1.
When the base class specifier is public, the access status of the inherited members remains unchanged. Thus, inherited public members are public, and inherited protected members are protected in a derived class.
- 2.
When the base class specifier is protected, both public and protected members of a base class are inherited as protected members.
- 3.
When the base class specifier is private, inherited public and protected members become private to the derived class, so they’re accessible by member functions of the derived class but cannot be accessed if they’re inherited in another derived class.

The effect of the base class specifier on the accessibility of inherited members
Access Specifiers and Class Hierarchies

The effect of access specifiers on base class members
You can prevent access to public base class members from outside the derived class—either specifier will do this. If the base class has public member functions, then this is a serious step because the class interface for the base class is being removed from public view in the derived class.
You can affect how the inherited members of the derived class are inherited in another class that uses the derived class as its base.

Affecting the access specification of inherited members
Constructors are not normally inherited for very good reasons, but you’ll see later in this chapter how you can cause constructors to be inherited in a derived class.
Choosing Access Specifiers in Class Hierarchies
You have two aspects to consider when defining a hierarchy of classes: the access specifiers for the members of each class and the base class access specifier in each derived class. The public members of a class define the external interface to the class, and this shouldn’t normally include any member variables. In fact:
Tip
As a rule, member variables of a class should always be private. If code outside of the class requires access to member variables, you should add public or protected getter and/or setter functions.
(This guideline commonly does not extend to structures. structs mostly do not encapsulate any member functions at all; the only members they typically have are public member variables.)
Data hiding allows you to preserve the integrity of an object’s state.
It reduces coupling and dependencies with external code, thus facilitating evolution and changes either in a class’s internal representation or in the concrete implementation of its interface functions.
It allows you to inject extra code to be executed for every access and/or modification of member variables. Beyond validity and sanity checks, this may include logging and debugging code, for instance, or change notification mechanisms.
It facilitates debugging, as most development environments support putting so-called debugging breakpoints on function calls. Putting breakpoints on getters and setters makes it much easier to track which code reads or writes to member variables and when.
There is nothing stopping a derived class from invalidating an object’s state, which may for instance invalidate so-called class invariants—properties of an object’s state that should hold at all times—counted on by code in the base class.
Once derived classes directly manipulate the member variables of a base class, changing its internal implementation becomes impossible without changing all of the derived classes as well.
Any extra code added to public getter and setter functions in the base class becomes void if derived classes can bypass it.
Breaking a debug session when member variables are modified becomes, at the least, more difficult if derived classes can access them directly, breaking when they’re read impossible.
Therefore, always make member variables private, unless you have a good reason not do so.
Note
To keep our code samples short, we will at times use protected member variables in this book. Such shortcuts have no place in professional-quality code, though.
Member functions that aren’t part of the public interface of a class should not be directly accessible from outside the class either, which means that they should be private or protected. Which access specification you choose for a particular function then depends on whether you want to allow access from within a derived class. If you do, use protected; otherwise, use private.
Changing the Access Specification of Inherited Members
You might want to exempt a particular base class member from the effects of a protected or private base class access specification. This is easier to understand with an example. Suppose you derive the Carton class from the Box class in Ex13_01 but with Box as a private base class. All members inherited from Box will now be private in Carton, but you’d like the volume() function to remain public in the derived class, as it is in the base class. You can restore the public status for a particular inherited member that was public in the base class with a using declaration.
This is essentially the same as the using declaration for namespaces. You can force the volume() function to be public in the derived class by defining the Carton class like this:
The class definition defines a scope, and the using declaration within the class definition introduces a name into that class scope. The member access specification applies to the using declaration, so the volume name is introduced into the public section of the Carton class so it overrides the private base class access specification for the volume() member of the base class. The function will be inherited as public in the Carton class, not as private. Ex13_01A in the code download shows this working.
There are several points to note here. First, when you apply a using declaration to the name of a member of a base class, you must qualify the name with the base class name, because this specifies the context for the member name. Second, note that you don’t supply a parameter list or a return type for a member function—just the qualified name. This implies that overloaded functions always come as a package deal. Third, the using declaration also works with inherited member variables in a derived class.
You can use a using declaration to override an original public or protected base class access specifier in a base class. For example, if the volume() function was protected in the Box base class, you could make it public in the derived Carton class with the same using declaration in a public section of Carton. However, you can’t apply a using declaration to relax the specification of a private member of a base class because private members cannot be accessed in a derived class.
Constructors in a Derived Class
If you put output statements in the constructors for the Carton class and the Box class and rerun the example, you’ll see what happens when a Carton object is created. You’ll need to define the default Box and Carton class constructors to include the output statements. Creating each Carton object always results in the default no-arg Box constructor being called first, followed by the Carton class constructor.
Derived class objects are always created in the same way, even when there are several levels of derivation. The most base class constructor is called first, followed by the constructor for the class derived from that, followed by the constructor for the class derived from that, and so on, until the constructor for the most derived class is called. This makes sense if you think about it. A derived class object has a complete base class object inside it, and this needs to be created before the rest of the derived class object. If that base class is derived from another class, the same applies.
Although in Ex13_01 the default base class constructor was called automatically, this doesn’t have to be the case. You can call a particular base class constructor in the initialization list for the derived class constructor. This will enable you to initialize the base class member variables with a constructor other than the default. It will also allow you to choose a particular base class constructor, depending on the data supplied to the derived class constructor. Let’s see it working in another example.
Here’s a new version of the Box class:
There are now three Box constructors, and they all output a message when they are called. operator<<() is defined as in Ex13_01.
The Carton class looks like this:
This class has four constructors, including a no-arg constructor. You must define this here because if you define any constructor, the compiler will not supply a default no-arg constructor. As always, we declare our single-argument constructor to be explicit to avoid unwanted implicit conversions.
Here’s the code to exercise this class:
The output is as follows:
Creating the first Carton object, carton1, results in the no-arg constructor for the Box class being called first, followed by the no-arg constructor for the Carton class.
Creating carton2 calls the no-arg Box constructor followed by the Carton constructor with a string_view parameter.
Creating the carton3 object calls the Box constructor with three parameters followed by the Carton constructor with four parameters.
Creating carton4 causes two Box constructors to be called because the Box constructor with a single parameter of type double that is called by the Carton constructor calls the Box constructor with three parameters in its initialization list.
This is all consistent, with constructors being called in sequence from the most base to the most derived.
Note
The notation for calling the base class constructor is the same as that used for initializing member variables in a constructor. This is perfectly consistent with what you’re doing here, because essentially you’re initializing the Box subobject of the Carton object using the arguments passed to the Carton constructor.
Although inherited member variables that are not private to the base class can be accessed from a derived class, they can’t be initialized in the initialization list for a derived class constructor. For example, try replacing the first Carton class constructor in Ex13_02 with the following:
You might expect this to work because length, width, and height are protected base class members that are inherited publicly, so the Carton class constructor should be able to access them. However, the compiler complains that length, width, and height are not members of the Carton class. This will be the case even if you make the member variables of the Box class public. If you want to initialize the inherited member variables explicitly, you could do it in the body of the derived class constructor. The following constructor definition would work:
By the time the body of the Carton constructor begins executing, the base part of the object has been created. In this case, the base part of the Carton object is created by an implicit call of the no-arg Box class constructor. You can subsequently refer to the names of the non-private base class members without a problem. Still, if possible, it is always best to forward constructor arguments to an appropriate base class constructor and have the base class deal with initializing the inherited members.
The Copy Constructor in a Derived Class
You already know that the copy constructor is called when an object is created and initialized with another object of the same class type. The compiler will supply a default copy constructor that creates the new object by copying the original object member by member if you haven’t defined your own version. Now let’s examine the copy constructor in a derived class. To do this, we’ll add to the class definitions in Ex13_02. First, we’ll add a copy constructor to the base class, Box, by inserting the following code in the public section of the class definition:
Note
You saw in Chapter 11 that the parameter for the copy constructor must be a reference.
This initializes the member variables by copying the original values and generates some output to track when the copy constructor is called.
Here’s a first attempt at a copy constructor for the Carton class:
Let’s see if this works (it won’t!):
This produces the following output:
All is not as it should be. Clearly the volume of cartonCopy isn’t the same as carton, but the output also shows the reason for this. To copy the carton object, you call the copy constructor for the Carton class. The Carton copy constructor should make a copy of the Box subobject of carton, and to do this it should call the Box copy constructor. However, the output clearly shows that the default Box constructor is being called instead.
The Carton copy constructor won’t call the Box copy constructor if you don’t tell it to do so. The compiler knows that it has to create a Box subobject for the object carton, but if you don’t specify how, the compiler won’t second-guess your intentions—it will just create a default base object.
Caution
When you define a constructor for a derived class, you are responsible for ensuring that the members of the derived class object are properly initialized. This includes all the directly inherited member variables, as well as the member variables that are specific to the derived class. Moreover, this applies to any constructor, including copy constructors.
The obvious fix for this is to call the Box copy constructor in the initialization list of the Carton copy constructor. Simply change the copy constructor definition to this:
The Box copy constructor is called with the carton object as an argument. The carton object is of type Carton, but it is also a perfectly good Box object. The parameter for the Box class copy constructor is a reference to a Box object, so the compiler will pass carton as type Box&, which will result in only the base part of carton being passed to the Box copy constructor. If you compile and run the example again, the output will be as follows:
The output shows that the constructors are called in the correct order. In particular, the Box copy constructor is called to create the Box subobject of carton before the Carton copy constructor. By way of a check, you can see that the volumes of the carton and cartonCopy objects are now identical.
The Default Constructor in a Derived Class
You know that the compiler will not supply a default no-arg constructor if you define one or more constructors for a class. You also know that you can tell the compiler to insert a default constructor in any event using the default keyword. You could replace the definition of the no-arg constructor in the Carton class definition in Ex13_02 with this statement:
Now the compiler will supply a definition, even though you have defined other constructors. The definition that the compiler supplies for a derived class calls the base class constructor, so it looks like this:
This implies that if the compiler supplies the no-arg constructor in a derived class, a non-private no-arg constructor must exist in the base class. If it doesn’t, the code will not compile. You can easily demonstrate this either by removing the no-arg constructor from the Box class in Ex13_02 or by making it private. With the compiler-supplied default constructor specified for the Carton class, the code will no longer compile. Every derived class constructor calls a base class constructor. If a derived class constructor does not explicitly call a base constructor in its initialization list, the no-arg constructor will be called.
Inheriting Constructors
Base class constructors are not normally inherited in a derived class. This is because a derived class typically has additional member variables that need to be initialized, and a base class constructor would have no knowledge of these. However, you can cause constructors to be inherited from a direct base class by putting a using declaration in the derived class. Here’s how a version of the Carton class from Ex13_02 could be made to inherit the Box class constructors:
If the Box class definition is the same as in Ex13_02, the Carton class will inherit two constructors: Box(double, double, double) and Box(double). The constructors in the derived class will look like this:
Each inherited constructor has the same parameter list as the base constructor and calls the base constructor in its initialization list. The body of each constructor is empty. You can add further constructors to a derived class that inherits from its direct base, as the Carton class example illustrates.
Unlike regular member functions, (non-private) constructors are inherited using the same access specifier as the corresponding constructor in the base class. So, even though the using Box::Box declaration is part of the implicitly private section of the Carton class, the constructors inherited from Box are both public. If the Box class would’ve had protected constructors, these would’ve been inherited as protected constructors in Carton as well.
Notice that one constructor of Box is flagrantly missing from the list of inherited constructors: the default constructor. That is, the using declaration did not cause a default constructor of the following form to be inherited:
Default constructors are never inherited. And because Carton explicitly defines a constructor (inherited constructors do not count here, by the way), the compiler did not generate a default default constructor either. Technically speaking, copy constructors are not inherited either, but you won’t notice this as the compiler mostly generates a default copy constructor anyway. You could try this by modifying Ex13_02 to create the following objects in main():
The resulting program is available online as Ex13_04. The output statements in the Box constructors will show that they are indeed called to create the first three objects. Of course, if you want Carton to have a default constructor, you could always instruct the compiler to generate one using the default keyword.
Destructors Under Inheritance
Destroying a derived class object involves both the derived class destructor and the base class destructor. You can demonstrate this by adding destructors with output statements in the Box and Carton class definitions. You can amend the class definitions in the correct version of Ex13_03. Add the destructor definition to the Box class:
And for the Carton class:
Of course, if the classes allocated free store memory and stored the address in a raw pointer, defining the class destructor would be essential to avoid memory leaks. The Carton destructor outputs the material so you can tell which Carton object is being destroyed by assigning a different material to each. Let’s see how these classes behave in practice:
Here’s the output:
Destructor Output | Object Destroyed |
|---|---|
Carton destructor. Material = Thin cardboard. | candyCarton object |
Box destructor. | Box subobject of candyCarton |
Carton destructor. Material = Cardboard. | carton object |
Box destructor. | Box subobject of carton |
This shows that the objects that make up a derived class object are destroyed in the reverse order from which they were created. The carton object was created first and destroyed last; the candyCarton object was created last and destroyed first. This order is chosen to ensure that you never end up with an object in an illegal state. An object can be used only after it has been defined—this means that any given object can only contain pointers (or references) that point (or refer) to objects that have already been created. By destroying a given object before any objects that it might point (or refer) to, you ensure that the execution of a destructor can’t result in any invalid pointers or references.
The Order in Which Destructors Are Called

The order of destructor calls for derived class objects
For an object with several levels of derivation classes, this order of destructor calls runs through the hierarchy of classes, starting with the most derived class destructor and ending with the destructor for the most base class.
Duplicate Member Variable Names
It’s possible that a base class and a derived class each have a member variable with the same name. If you’re really unlucky, you might even have names duplicated in the base class and in an indirect base. Of course, this is confusing, and you should never deliberately set out to create such an arrangement in your own classes. However, circumstances or oversights may make that this is how things turn out. So, what happens if member variables in the base and derived classes have the same names?
Duplication of names is no bar to inheritance, and you can differentiate between identically named base and derived class members. Suppose you have a class Base, defined as follows:
This just contains a single member variable, value, and a constructor. You can derive a class Derived from Base as follows:
The derived class has a member variable called value, and it will also inherit the value member of the base class. You can see that it’s already starting to look confusing! We’ll show how you can distinguish the two members with the name value in the derived class by writing a definition for the total() function . Within the derived class member function, value by itself refers to the member declared within that scope, that is, the derived class member. The base class member is declared within a different scope, and to access it from a derived class member function, you must qualify the member name with the base class name. Thus, you can write the total() function as follows:
The expression Base::value refers to the base class member, and value by itself refers to the member declared in the Derived class.
Duplicate Member Function Names

Inheriting a function with the same name as a member function
The second possibility is that both functions have the same function signature. You can still differentiate the inherited function from the derived class function by using the class name as a qualifier for the base class function:
However, there’s a lot more to this latter case than we can discuss at this point. This subject is closely related to polymorphism, which is explored in much more depth in the next chapter.
Multiple Inheritance
So far, your derived classes have all been derived from a single direct base class. However, you’re not limited to this structure. A derived class can have as many direct base classes as an application requires. This is referred to as multiple inheritance as opposed to single inheritance, in which a single base class is used. This opens vast new dimensions of potential complexity in inheritance, which is perhaps why multiple inheritance is used much less frequently than single inheritance. Because of the complexity, it is best used judiciously. We’ll just explain the basic ideas behind how multiple inheritance works.
Multiple Base Classes
Multiple inheritance involves two or more base classes being used to derive a new class, so things are immediately more complicated. The idea of a derived class being a specialization of its base leads in this case to the notion that the derived class defines an object that is a specialization of two or more different and independent class types concurrently. In practice, multiple inheritance is rarely used in this way. More often, multiple base classes are used to add the features of the base classes together to form a composite object containing the capabilities of its base classes, sometimes referred to as mixin programming. This is usually for convenience in an implementation rather than to reflect any particular relationships between objects. For example, you might consider a programming interface of some kind—for graphics programming, perhaps. A comprehensive interface could be packaged in a set of classes, each of which defines a self-contained interface that provides some specific capability, such as drawing two-dimensional shapes. You can then use several of these classes as bases for a new class that provides precisely the set of capabilities you need for an application.

An example of multiple inheritance
The definition of the CerealPack class looks like this:
Each base class is specified after the colon in the class header, and the base classes are separated by commas. Each base class has its own access specifier, and if you omit the access specifier, private is assumed, the same as with single inheritance. The CerealPack class will inherit all the members of both base classes, so this will include the members of the indirect base, Box. As in the case of single inheritance, the access level of each inherited member is determined by two factors: the access specifier of the member in the base class and the base class access specifier. A CerealPack object contains two subobjects, a Contents subobject and a Carton subobject that has a further subobject of type Box.
Inherited Member Ambiguity
Multiple inheritance can create problems. We’ll put together an example that will show the sort of complications you can run into. The Box class is the same as in Ex13_05, but we’ll extend the Carton class from that example a little:
We’ve added two member variables that record the thickness and density of the material from which the Carton object is made; a new constructor that allows all member variables to be set; and a new member function, getWeight(), which calculates the weight of an empty Carton object. The new constructor calls another Carton class constructor in its initialization list, so it is a delegating constructor, as you saw in Chapter 11. A delegating constructor cannot have further initializers in the list, so the values for density and thickness have to be set in the constructor body.
The Contents class will describe an amount of a dry product, such as breakfast cereal, that can be contained in a carton. The class will have three member variables: name, volume, and density (in pounds per cubic inch). In practice, you would probably include a set of possible cereal types, complete with their densities, so that you could validate the data in the constructor, but we’ll ignore such niceties in the interest of keeping things simple. Here’s the class definition along with the preprocessing directives that you need in the header file, Contents.h:
In addition to the constructors and the destructor, the class has a public member function, getWeight(), to calculate the weight of the contents. Note how the name member is initialized in the member initializer list with the parameter value that has the same name. This is just to illustrate that this is possible—not a recommended approach. We’ll define the CerealPack class with the Carton and Contents classes as public base classes:
This class inherits from both the Carton and Contents classes. The constructor requires only the external dimensions and the cereal type. The material for the Carton object is set in the Carton constructor call, in the initialization list. A CerealPack object will contain two subobjects corresponding to the two base classes. Each subobject is initialized through constructor calls in the initialization list for the CerealPack constructor. Note that the volume member variable of the Contents class is zero by default, so, in the body of the CerealPack constructor, the value is calculated from the size of the carton. The reference to the volume member variable inherited from the Contents class must be qualified here because it’s the same as the name of the function inherited from Box via Carton. You’ll be able to trace the order of constructor and destructor calls from the output statements here and in the other classes.
Let’s try creating a CerealPack object and calculate its volume and weight with the following simple program:
Unfortunately, there’s a problem. The program won’t compile. The difficulty is that we have foolishly used some nonunique function names in the base classes. The name volume is inherited as a function from Box and as a member variable from Contents , and the getWeight() function is inherited from Carton and from Contents in the CerealPack class. There’s more than one ambiguity problem.
Of course, when writing classes for use in inheritance, you should avoid duplicating member names in the first instance. The ideal solution to this problem is to rewrite your classes. If you are unable to rewrite the classes—if the base classes are from a library of some sort, for example—then you would be forced to qualify the function names in main(). You could amend the output statement in main() to get the code to work:
With this change, the program will compile and run, and it will produce the following output:
You can see from the output that this cereal will give you a solid start to the day—a single packet weighs more than six pounds. You can also see that the constructor and destructor call sequences follow the same pattern as in the single inheritance context: the constructors run down the hierarchy from most base to most derived, and the destructors run in the opposite order. The CerealPack object has subobjects from both legs of its inheritance chain, and all the constructors for these subobjects are involved in the creation of a CerealPack object.
An alternative way of making Ex13_06 compile, by the way, is by adding casts to a reference to either of the base classes (we cast to a reference and not the class type itself to avoid the creation of a new object):
A working version along these lines is in the code download as Ex13_06A.
But, wait, we’re not done yet! There’s yet another way of ensuring that this compiles—one that is definitely worth mentioning as well. Clearly it is inconvenient that users of your CerealPack class always have to disambiguate the volume() and getWeight() members. Luckily, you can typically prevent this from happening. Suppose we insist in the insanity that a CerealPack’s volume should always be computed using the volume() member of Carton and its weight using the getWeight() member of Contents. Then you could stipulate this property as such in the definition of its class (see Ex13_06B) as follows:
Earlier this chapter you encountered a similar use of the using keyword to inherit constructors from the base class. In this case you use it to cherry-pick from which base class a multiply inherited member function needs to be inherited. Now CerealPack users—or breakfast eaters, as they are more commonly known as—can simply write this:
Clearly this last option is thus preferred whenever there is a clear answer as to which multiply inherited members should be used. If you disambiguate the inheritance already in the class definition, it saves the users of your class the hassle of fighting against the compiler errors that would otherwise surely follow.
Repeated Inheritance

Duplicate base classes in a derived class
The CerealPack class inherits all the members of both the Contents and Carton classes. The Carton class inherits all the members of the Box class, and both the Box and Contents classes inherit the members of the Common class. Thus, as Figure 13-9 shows, the Common class is duplicated in the CerealPack class. The effect of this on objects of type CerealPack is that every CerealPack object will have two subobjects of type Common. The complications and ambiguities that arise from such repeated inheritance are often referred to as the diamond problem—named after the shape of inheritance diagrams such as Figure 13-9.
It is conceivable that you actually want to allow the duplication of the Common class. In this case, you must qualify each reference to the Common class member so that the compiler can tell which inherited member you’re referring to in any particular instance. In this case, you can do this by using the Carton and Contents class names as qualifiers because each of these classes contains a unique subobject of type Common. Of course, to call the Common class constructors when you’re creating a CerealPack object, you would also need qualifiers to specify which of the two base objects you were initializing. More typically, though, you would want to prevent the duplication of a base class, so let’s see how to do that.
Virtual Base Classes
To avoid duplication of a base class, you must identify to the compiler that the base class should appear only once within a derived class. You do this by specifying the class as a virtual base class using the virtual keyword. The Contents class would be defined like this:
The Box class would also be defined with a virtual base class:
Now any class that uses the Contents and Box classes as direct or indirect bases will inherit the other members of the base classes as usual but will inherit only one instance of the Common class. The derived CerealPack class would inherit only a single instance of the Common base class. Because there is no duplication of the members of Common in the CerealPack class, no qualification of the member names is needed when referring to them in the derived class.
Converting Between Related Class Types
Every derived class object has a base class object inside it waiting to get out. Conversions from a derived type to its base are always legal and automatic. Here’s a definition of a Carton object:
We have already seen two ways this object can be converted to a base class object of type Box. The first is by means of a copy constructor:
And the second is a copy assignment:
Both convert the carton object to a new object of type Box and store a copy of it in box. The assignment operator that is used is the default assignment operator for the Box class. Of course, only the Box subobject part of carton is used; a Box object has no room for the Carton-specific member variables. This effect is called object slicing , as the Carton specific portion is sliced off, so to speak, and discarded.
Caution
Object slicing is something to beware of in general because it can occur when you don’t want a derived class object to have its derived members sliced off. In the next chapter, you will learn about the mechanism that allows working with pointers or references to base class objects, while preserving the members and even behavior of the derived class.
Conversions up a class hierarchy (that is, toward the base class) are legal and automatic as long as there is no ambiguity. Ambiguity can arise when two base classes each have the same type of subobject. For example, if you use the definition of the CerealPack class that contains two Common subobjects (as you saw in the previous section) and you initialize a CerealPack object, cornflakes, then the following will be ambiguous:
The compiler won’t be able to determine whether the conversion of cornflakes should be to the Common subobject of Carton or to the Common subobject of Contents. The solution here would be to cast cornflakes to either Carton& or Contents&. Here’s an example:
You can’t obtain automatic conversions for objects down a class hierarchy—that is, toward a more specialized class. A Box object contains no information about any class type that may be derived from Box, so the conversion doesn’t have a sensible interpretation. In the next chapter, you’ll see that pointers and references are different. A pointer or reference to a base class type can store the address of a derived class object, in which case you can cast it to one for the derived class type.
Summary
In this chapter, you learned how to define a class based on one or more existing classes and how class inheritance determines the makeup of a derived class. Inheritance is a fundamental characteristic of object-oriented programming, and it makes polymorphism possible (polymorphism is the subject of the next chapter). The important points to take from this chapter include the following:
A class may be derived from one or more base classes, in which case the derived class inherits members from all of its bases.
Single inheritance involves deriving a class from a single base class. Multiple inheritance involves deriving a class from two or more base classes.
Access to the inherited members of a derived class is controlled by two factors: the access specifier of the member in the base class and the access specifier of the base class in the derived class declaration.
A constructor for a derived class is responsible for initializing all members of the class, including the inherited members.
Creation of a derived class object always involves the constructors of all of the direct and indirect base classes, which are called in sequence (from the most base through to the most direct) prior to the execution of the derived class constructor.
A derived class constructor can, and often should, explicitly call constructors for its direct bases in the initialization list for the constructor. If you don’t call one explicitly, the base class’s default constructor is called. A copy constructor in a derived class, for one, should always call the copy constructor of all direct base classes.
A member name declared in a derived class, which is the same as an inherited member name, will hide the inherited member. To access the hidden member, use the scope resolution operator to qualify the member name with its class name.
You can use using not only for type aliases but also to inherit constructors (always with the same access specification as in the base class), to modify the access specifications of other inherited members, or to inherit functions that would otherwise be hidden by a derived class’s function with the same name but different signature.
When a derived class with two or more direct base classes contains two or more inherited subobjects of the same class, the duplication can be prevented by declaring the duplicated class as a virtual base class.
Exercises
Exercise 13-1. Define a base class called Animal that contains two private member variables: a string to store the name of the animal (e.g., “Fido” or “Yogi”) and an integer member called weight that will contain the weight of the animal in pounds. Also include a public member function, who(), that outputs a message giving the name and weight of the Animal object. Derive two classes named Lion and Aardvark, with Animal as a public base class. Write a main() function to create Lion and Aardvark objects (“Leo” at 400 pounds and “Algernon” at 50 pounds, say) and demonstrate that the who() member is inherited in both derived classes by calling it for the derived class objects.
Exercise 13-2. Change the access specifier for the who() function in the Animal class to protected, but leave the rest of the class as before. Now modify the derived classes so that the original version of main() still works without alteration.
Exercise 13-3. In the solution to the previous exercise, change the access specifier for the who() member of the base class back to public, and implement the who() function as a member of each derived class so that the output message also identifies the name of the class. Change main() to call the base class and derived class versions of who() for each of the derived class objects.
Exercise 13-4. Define a Person class containing member variables for age, name, and gender. Derive an Employee class from Person that adds a member variable to store a personnel number. Derive an Executive class from Employee. Each derived class should define a member function who() that displays information about what it is. Think carefully about proper data hiding and access specifiers in this exercise. In this particular application, privacy concerns prohibit the exposure of personal details, except for the information printed by an object’s who() member. Each class can decide explicitly what to expose there. (Name and type will do—something like “Fred Smith is an Employee.”) Furthermore, people also aren’t allowed to change name or gender, but they are allowed to have birthdays. Write a main() function to generate a vector of five executives and a vector of five ordinary employees and display information about them. In addition, display the information on the executives by calling the member function inherited from the Employee class.