Search

11.2 — Basic inheritance in C++

Now that we’ve talked about what inheritance is in an abstract sense, let’s talk about how it’s used within C++.

Inheritance in C++ takes place between classes. When one class inherits from another, the derived class acquires the members (both variables and functions) of the base class. These variables and functions become members of the derived class.

A Person class

Here’s a simple class to represent a generic person:

Because this Person class is designed to represent a generic person, we’ve only defined members that that would be common to any type of person. Every person (regardless of gender, profession, etc…) has a name and age, so those are represented here.

Note that in this example, we’ve made all of our variables and functions public. This is purely for the sake of keeping these examples simple right now. Normally we would make the variables private. We will talk about access controls and how those intersect with inheritance later in this chapter.

A BaseballPlayer class

Let’s say we wanted to write a program that keeps track of information about some baseball players. Baseball players need to contain information that is specific to baseball players -- for example, we might want to store a player’s batting average, and the number of home runs they’ve hit.

Here’s our incomplete Baseball player class:

Now, we also want to keep track of a baseball player’s name and age, and we already have that information as part of our Person class.

We have three choices for how to add name and age to BaseballPlayer:
1) Add name and age to the BaseballPlayer class directly as members. This is probably the worst choice, as we’re duplicating code that already exists in our Person class. Any updates to Person will have to be made in BaseballPlayer too.
2) Add Person as a member of BaseballPlayer using composition. But we have to ask ourselves, “does a BaseballPlayer have a Person”? No, they don’t. So this isn’t the right paradigm.
3) Have BaseballPlayer inherit those attributes from Person. Remember that inheritance represents an is-a relationship. Is a BaseballPlayer a Person? Yes, they are. So inheritance is a good choice here.

Making BaseballPlayer a derived class

To have BaseballPlayer inherit from our Person class, the syntax is fairly simple. After the class BaseballPlayer declaration, we use a colon, the word “public”, and the name of the class we wish to inherit. This is called public inheritance. We’ll talk more about what public inheritance means in a future lesson.

Using a derivation diagram, our inheritance looks like this:

When BaseballPlayer inherits from Person, BaseballPlayer receives the member functions and variables from Person. Thus, BaseballPlayer objects will have 4 member variables: m_battingAverage and m_homeRuns from BaseballPlayer, and m_name and m_age from Person.

This is easy to prove:

Which prints the value:

Joe

This compiles and runs because joe is a BaseballPlayer, and all BaseballPlayer objects have a m_name member variable that they inherit from the Person class.

An Employee derived class

Now let’s write another class that also inherits from Person. This time, we’ll write an Employee class. An employee “is a” person, so using inheritance is appropriate:

Employee inherits m_name and m_age from Person (as well as the two access functions), and adds two more member variables and a member function of its own. Note that printNameAndSalary() uses variables both from the class it belongs to (Employee::m_hourlySalary) and the parent class (Person::m_name).

This gives us a derivation chart that looks like this:

Note that Employee and BaseballPlayer don’t have any direct relationship, even though they both inherit from Person.

Here’s a full example using Employee:

This prints:

Frank: 20.25

Inheritance chains

It’s possible to inherit from a class that is itself derived from another class. There is nothing noteworthy or special when doing so -- everything proceeds as in the examples above.

For example, let’s write a Supervisor class. A Supervisor is an Employee, which is a Person. We’ve already written an Employee class, so let’s use that as the base class from which to derive Supervisor:

Now our derivation chart looks like this:

All Supervisor objects inherit the functions and variables from both Employee and Person, and add their own m_nOverseesIDs member variable.

By constructing such inheritance chains, we can create a set of reusable classes that are very general (at the top) and become progressively more specific at each level of inheritance.

Why is this kind of inheritance useful?

Inheriting from a base class means we don’t have to redefine the information from the base class in our derived classes. We automatically receive the member functions and member variables of the base class through inheritance, and then simply add the additional functions or member variables we want. This not only saves work, but also means that if we ever update or modify the base class (e.g. add new functions, or fix a bug), all of our derived classes will automatically inherit the changes!

For example, if we ever added a new function to Person, both Employee and Supervisor would automatically gain access to it. If we added a new variable to Employee, Supervisor would also gain access to it. This allows us to construct new classes in an easy, intuitive, and low-maintenance way!

Conclusion

Inheritance allows us to reuse classes by having other classes inherit their members. In future lessons, we’ll continue to explore how this works.

11.3 -- Order of construction of derived classes
Index
11.1 -- Introduction to inheritance

22 comments to 11.2 — Basic inheritance in C++

  • davidv

    Is the inheritance chart necessarily a tree? In other words, could Supervisor have inherited both BaseballPlayer and Employee at the same time?

  • o.o!

    class Supervisor: public Employee
    {
    public:
    // This Supervisor can oversee a max of 5 employees
    int m_nOverseesIDs[5]; // <== [4]?
    };

  • edgeoftheworld

    Thank you very much for your tutorials. They are a great help :).
    -cheers.

  • momalok

    Hi Alex.
    Im a bit confused with your employee supervisor example. Surely a supervisor both HAS an employee and IS an employee, so how would we know in this case which one of composition or inheritance to utilise?
    I understand the rest of it fine, im just not sure on that little bit, or if the example exhibits chain inheritance well enough.
    Thanks.

    • Alex

      You’d use both. Because the Supervisor itself “is-an” Employee, it should use inheritance to become a subclass of Employee. Because the supervisor “has” employee IDs, it can use composition to store the Employee IDs.

  • vish

    Hey..make me clear here..in the inheritance chaining the supervisor can use the person class or not?
    And if not how two classes can be inherited in one class?

  • chandu

    Hi,

    please observe my code, it’s follows:

    [[

    #include <iostream>

    #include <string>

    using namespace std;

    class person
    {
            private:
                  string c_mName;
                  int c_mAge;
                  bool c_mSex;
                  
            public:
                
                 person(string c_fName, int c_fAge, bool c_fSex):
                               c_mName (c_fName), c_mAge(c_fAge), c_mSex(c_fSex)
                 {
          
                 }
                
                 string Get_mName(void)
                 {
                        return c_mName;
                 }
                
                 int Get_mAge(void)
                 {
                     return c_mAge;
                 }
                
                 bool Get_mSex(void)
                 {
                      return c_mSex;
                 }
                
                 void Set_mName(string c_fName)
                 {
                      c_mName = c_fName;
                 }
                
                 void Set_mAge(int c_fAge)
                 {
                      c_mAge = c_fAge;
                 }
                
                 void Set_mSex(bool c_fSex)
                 {
                      c_mSex = c_fSex;
                 }
                
                 friend istream& operator >> (istream &in, person &c_person)
                 {
                        in >> c_person.c_mName;
                        in >> c_person.c_mAge;
                        in >> c_person.c_mSex;
                        
                        return in;
                 }
                
                 friend ostream& operator << (ostream &out, person &c_person)
                 {
                        out << c_person.c_mName<<endl <<
                               c_person.c_mAge<<endl << c_person.c_mSex<<endl;
                        return out;
                 }
                
                                          
    };

    class cricket_player : public person
    {
          private:
                  string c_mState;
                  int c_mJersyNum;
                  
          public:
                 cricket_player(string c_fName, int c_fAge, bool c_fSex, string c_fState, int c_fJersyNum) :
                              person(c_fName, c_fAge, c_fSex) , c_mState(c_fState), c_mJersyNum(c_fJersyNum)  
                 {
                              
                 }
                  string Get_mPlayerState(void)
                  {
                         return c_mState;
                  }
                  
                  int Get_mPlayerJesryNum(void)
                  {
                      return c_mJersyNum;
                  }
                  
                  friend ostream& operator << (ostream &out, cricket_player &c_player)
                 {
                        out  << c_player.c_mState<<endl <<
                                c_player.c_mJersyNum<<endl;
                        return out;
                 }
    };

    int main()
    {
        cricket_player c_obj1("chandu", 24, 1, "telangana", 1);
        
        cout << "enter the name,age,sex of a player: ";
        
        cin >> c_obj1;
        
        cout << c_obj1;
        
        getchar();
        getchar();
    }
    ]]

    My question is how to overload the <<(out) operator of the base class with the derived class object? there is any possible way for it to print the base class members with the overloading output operator (or) we could access through member functions only??

    please run the code & understand it???????

    here my expected display is:
    name
    age
    sex
    state
    jersynum with the help of overloading of out (>>) operator,
    but i got the output like:
    state
    jersy num
    how to get entire expected output with operator overloading concept? there is any possibility for it??????

    • Alex

      You can use a dynamic_cast to convert a reference to a derived class object into a reference to a base class object.

      Add the following line to the top of your output operator for cricket_player:

  • Vaibhav

    Hi Alex;
    I don’t get it why is it necessary to initialize a default constructor, why cant we define a parametrized one??

  • Matt

    For your Person class, in your getName() function, you returned "m_bame" instead of "m_name".

  • Matt

    In the code directly above the section titled "Inheritance chains", in the Employee class, 2nd member variable, you wrote "long m_lEmployeeID" instead of "long m_employeeID".

  • Tomas

    There is a couple of typos in a employee class, line10 std::string getName() const { return m_bame; } should m_name

    and I believe lane40 frank.m_name = ‘Frank’; // it should be "Frank" shouldnt it?

    Other from that really impressive work!

    However, I have a question. In first example Person Class you use getName and getAge and use these functions to cout, wouldnt it be more useful to overload std::ostream& operator?

    • Alex

      Thanks for pointing out the typos. They’re fixed.

      Yes, we could have just as easily provided an overloaded operator<<. However, using a normal function seemed more straightforward (no dealing with friends or overloaded operators) since that's not what the example was trying to show.

Leave a Comment

Put C++ code inside [code][/code] tags to use the syntax highlighter