In Object Oriented Programming, Inheritance is the process by which objects of one class acquire the properties and functionality of objects of another class. It supports the concept of hierarchical classification. For example, the bird robin is a part of the class flying bird which is again a part of the class bird.

One reason to use inheritance is that it allows you to reuse code from a previous project but gives you the flexibility to slightly modify it if the old code doesn’t do exactly what you need for the new project. It doesn’t make sense to start every new project from scratch since some code will certainly be repeated in several programs and you should strive to build on what you did previously. Moreover, it is easy to make an error if we try to modify the original class, but we are less likely to make an error if we leave the original alone and only add to it. Another reason for using inheritance is if the project requires the use of several classes which are very similar but slightly different.

In this tutorial we will concentrate on the mechanism of inheritance and how to build it into a program. A better illustration of why you would use inheritance will be given in later tutorials where we will discuss some practical applications of object oriented programming.

Table of Contents

The principle of inheritance is available with several modern programming languages and is handled slightly differently with each. C++ allows you to inherit all or part of the members and methods of a class, modify some, and add new ones not available in the parent class. You have complete flexibility, and as usual, the method used with C++ has been selected to result in the most efficient code execution.

Start with a simple C++ Class

First, example the file named vehicle.h below for a simple class which we will use to begin our study of inheritance in this chapter. The header file uses #ifndef and #define directives to define the class.

This class header is straightforward and uncomplicated. It includes four methods designed for manipulating vehicle-related data. The specifics of each method are not crucial at this moment. While we’ll later identify it as a base or parent class, for now, treat it like any other class to highlight its similarity to previously studied classes. The explanation of the added keyword “protected” will follow shortly.

You can not compile or execute this file because it is only a header file

The Implementation of the Class

Examine the program named vehicle.cpp as below and you will find that it is the implementation of the vehicle class.

The “initialize()” method assigns input values to the “wheels” and “weight” variables. Methods are in place to retrieve the number of wheels and weight, along with one performing a simple calculation to yield the load on each wheel. While more complex methods will be explored later, our current focus is on setting up class interfaces, keeping the implementations straightforward.

This class is uncomplicated and serves as a building block for the upcoming program. In subsequent tutorials, we’ll utilize it as a base class. Compile the class in preparation for the next example, but note that it lacks an entry point and cannot be executed at this stage.

Using the Vehicle Class

The program named transport.cpp below uses the vehicle class in exactly the same manner as we illustrated in the last chapter.

Output of the Program:

This signals that the vehicle class is essentially a standard C++ class. However, we’ll give it a unique touch by utilizing it unaltered as a base class in the upcoming example files to showcase inheritance. Inheritance involves enhancing an existing class to perform another, potentially more intricate task.

Understanding the inner workings of this program should be easy. It declares four vehicle class objects, initializes them, and outputs selected data points to demonstrate that the vehicle class functions effortlessly as a simple class—just as it is. For now, we’re keeping it simple and avoiding terms like “base class” or “derived class,” which we’ll delve into shortly.

Introducing Derived Classes

Take a look at the program named “car.h” for our first example of utilizing a derived class, also known as a child class.

The magic happens on line 4 with the addition of “: public vehicle,” which signifies that the “car” class inherits from the “vehicle” class. This derived class, “car,” encapsulates all the information from the base class, “vehicle,” and adds its unique details. Although we made no alterations to the “vehicle” class, it becomes a base class due to our utilization here. Notably, it can continue being used as a simple class in the earlier example program while also serving as a base class in a subsequent example program in this chapter. Its classification as a simple class or a base class depends on how it’s employed.

You can read more about Encapsulation in this tutorial: Encapsulation

In object-oriented programming, a class inheriting another is often called a derived class or a child class. The proper C++ term is “derived class“. Similarly, the formal C++ term for the inherited class is a base class, but you might encounter “parent class” or “superclass.”

A base class is quite general, covering a broad spectrum of objects. On the other hand, a derived class is somewhat more specific yet more practical. For instance, consider a base class named “programming language” and a derived class named “C++.” The base class can define Pascal, Ada, C++, or any programming language, providing a general perspective for each. Meanwhile, the derived class, “C++,” can specifically detail the use of classes but lacks the versatility to describe other languages. A base class tends to be more general, whereas a derived class is more specific.

In this scenario, the “vehicle” base class can declare objects representing trucks, cars, bicycles, or various other vehicles. Conversely, the “car” class can only declare objects of the car type due to limited applicable data. Hence, the “car” class is more restrictive and specific, while the “vehicle” class is broader and more general.

Declaring a Derived Class

Defining a derived class involves the header file for the base class, as seen in line 2. Then, following the name of the derived class in line 4, add a colon and the name of the base class. Objects declared as part of the “car” class inherit the two variables from the “vehicle” class and the unique variable declared in the “car” class named “passenger_load.”

An object of this class encompasses three of the four methods from the “vehicle” class and the two new ones declared here. Note that the “initialize()” method from the “vehicle” class is not available here, as it’s overridden by the local version in the “car” class. The local method takes precedence when the name is repeated, allowing customization of your new class.

It’s essential to reiterate that the implementation for the base class only needs to be supplied in its compiled form. Hiding the source code aids software developers for economic reasons and allows the practice of information hiding. The header for the base class must be available as a text file since the class definitions are necessary for usage.

Car Class Implementation

Examine the file named “car.cpp,” the implementation file for the “car” class:

Notice that this file doesn’t explicitly indicate that it’s a derived class. Its status can only be determined by inspecting the header file for the class. Written in the same way as any other class implementation file, it hides its derived nature.

The implementations for the two new methods are crafted just like methods for any other class. If you believe you’ve grasped this file, go ahead and compile it for later use.

Another Derived Class

Check out the file named “truck.h” for another example of a class utilizing the “vehicle” class and adding to it:

It adds different elements because it specializes in things related to trucks, introducing two more variables and three methods. Again, ignore the “public” keyword following the colon for a few minutes.

A crucial point is that the “car” class and the “truck” class are independent; they are just derived classes of the same base class or parent class, as it’s sometimes called.

Note that both the “car” and the “truck” classes have methods named “passengers()”—this poses no problem and is perfectly acceptable. If classes are related, especially if they’re both derived classes of a common base class, it’s reasonable for them to perform somewhat similar tasks. In such cases, method names might be repeated in both child classes.

Truck Implementation

Examine the file named “truck.cpp” for the implementation of the “truck” class. It contains nothing unusual:

Using all three Classes

Explore the example program named “allvehicle.cpp” to see how all three classes discussed in this chapter can be utilized.

This program utilizes the parent class “vehicle” to declare objects and also leverages the two child classes to declare objects. The inclusion of all three class header files in lines 3 through 5 allows the program to access the components of these classes. Note that the actual implementations of the classes are not visible here, demonstrating the ability to use the code without exposing its source. However, the header file definition must be accessible.

In this example program, only one object of each class is declared and used, but you can declare and use as many as needed for your programming task. The source code remains clean and uncluttered since the classes were developed, debugged, and stored away beforehand, with simple interfaces. The program’s operation should be straightforward if you are familiar with the concepts discussed.

The three classes and the main program can be compiled in any desired order before linking the resulting object files together. Ensure you follow the necessary steps to compile and execute this program, as effective C++ usage often involves compiling and linking multiple files.

Our First Practical Inheritance

We have a date class as defined by date.h program below.

Now we are introducing a new member variable, day_of_year, and a corresponding method. While there might be more efficient ways to add day_of_year, our primary focus is to provide a tangible illustration of inheritance rather than crafting a flawless class. The new_date class, therefore, features the addition of one variable and one method.

The accompanying program, newdate.cpp, implements the added method, leveraging the array “days[]” from the date class implementation. The logic in the “get_day_of_year()” method is straightforward, adjusting for leap years while keeping simplicity in mind.

Now in the following C++ program we demonstrate the new class in a simple manner to emphasize that the derived class is just as user-friendly as the base class. The main program remains unaware that it is working with a derived class.

Compile and link this program to gain hands-on experience. Remember to link the object code for the original date class, the newdate class, and the main program.