Private Inheritance in C++


Reading time: 20 minutes | Question Solving time: 10 minutes

In this article, we will be learning about Private Inheritance in Object Oriented Programming (OOP) with reference to C++. Private inheritance involves the use of Private Access Specifiers for its member functions and data members.

What is inheritance in C++?

Now before getting into the topic, one must be aware of what inheritance is. Inheritance, as the name suggests, helps us to define a class using the properties of another class, the class from which the properties are inherited is known as the parent class or base class and the class which inherits the parent class is known as the child class or derived class.

Now inheritance involves the concept of access specifiers which specifies the visibility and access modes in the derived class. In C++, the general format for deriving the base class is:

class <derived-class> : access-specifier <base-class>
{ // body of the class
};

Here, the access specifier could be public, protected, or private.

Among these types of inheritance, public inheritance is the most widely used inheritance and there are very limited resources to the non-public kind of inheritance. Many questions may arise on the use of non-public ones as their applications would be rarely visible to us in our daily lives.

Inheritance with Private Access Specifier

The whole concept of inheritance aims at reusability and improving the functionality of programming keeping in mind, hiding the non-essential features of the class (data abstraction).

Now, in Private inheritance,

  • the public and protected members of the base class become private members of the derived class
  • the private members of the base class cannot be accessed by the derived class.
  • the interface of the base class is not being inherited but its implementation is being inherited which means one can use the contents of the base class as it is using the member functions of the derived class.

Let us consider a class for better understanding:

class A
{
    private:
        int p;
        int fp();
    public:
        int q;
        void fq();
    protected:
        int r;
        void fr();
};

class B : private  A
{
    private:
        int s;
    public:
        int t;
        void ft();
     
};

int M()
{
    ----
}


int main()
{
    A obj_a;
    B obj_b;
    ---
}

Let us analyze this example, a table is shown below whether the following would be able to access the contents of class or not.

Entity Access
obj_a can use q, fq()
int fp() can use p, q, fq(), r, fr()
obj_b can use t, ft()
void ft() can use q, fq(), r, fr(), s, t
int M() can only use what obj_a and obj_b can use

Now the question here arises is, why do we need private inheritance?

Inheritance follows the concept of IS-A relationship, for example, Car is a vehicle, Truck is a vehicle where Car and Truck are derived classes and Vehicle is the base class. Now Private Inheritance is not IS-A relationship but is used to implement HAS-A relationship. Let us consider one more statement, Car has a Seat where Car is the base class and Seat is the derived class. Now, Car and Seat do not have a particular relationship but Seat wants to use some members of the Car avoiding its further use by any other classes or functions, this is what this inheritance provides. Precisely, this inheritance can be written as:

The Base Class HAS-A Derived Class
OR
The Base Class IS-A relation in terms of Derived Class

We will now closely study an example of how private inheritance could be implemented to represent IS-A relationship. We'll take two classes named Zoo and Animal.

#include <iostream>
using namespace std;

class Zoo
{
    private:
        int zoo_id;
     
    public:
        char place[50];
        
        int getID()
        {
            return zoo_id;
        }
        
        Zoo(int id)       // constructor
        {
          zoo_id = id;
        }
        
        void print()
        {
        cout<<"this is the ID of the Zoo:"<<zoo_id<<endl;
        } 
};

class Animal: private Zoo
{
//Zoo has-a Animal
    public:
        Animal(int id = 45) : Zoo(id) { }   //derived class constructor
        
        void print() {               // function of Zoo is overriden
	cout << "Zoo with " << Zoo::getID() <<
		   "ID is now open with this animal" << endl;
	Zoo:: print();       // calling the function of Zoo
   }
};

int main()
{
    Animal a(123);
    a.print();  // object will call function of Animal
    return(0);
}

OUTPUT

Zoo with 123ID is now open with this animal
this is the ID of the Zoo:123

In the above example, there are some points which should be noted:

  • The object 'a' cannot access any member of the Zoo class directly.
  • It is still possible to access the members of Zoo using functions of class Animal.
  • Private members of Zoo can be accessed using member functions of Zoo which will eventually be private functions of Animal.
  • In short, Animal is acquiring the implementation of Zoo but not the interface.
  • The private inheritance allows Animal to override Zoo's virtual functions.

HAS-A relationship can also be implemented using Composition which is nothing but having features/implementation of existing class into a new class using the object of an existing class in the new class.

Advantages of Private Inheritance over Composition & Applications



  • Stronger Binding
    The concept inheritance has the strongest relationship among the objects which means Private Inheritance has a strong binding concept whereas Composition is a looser form of binding.
  • Virtual Functions
    Whenever there is a need to override a virtual function in some class, private inheritance is the best to use.
  • Optimization
    Private Inheritance is used in "Empty Base Class Optimization" which involves the use of empty classes for optimizing sizes of objects in a program.
  • Protected Members
    In some exceptional cases, this could also be used for accessing protected members of the class in a HAS-A relationship problem as in this case composition could not be used and it is a must that we use inheritance.

Summary

Private Inheritance inherits the public and protected members of the base class as private members in the derived class and implements HAS-A relationship instead of IS-A relationship. The example of Zoo and Animal explains how accessibility would work in this case and one can override a virtual function using this concept. Moreover, HAS-A relationship could also be implemented using Composition but then it has its own set of restrictions as inheritance is a fundamental concept of Object Oriented Programming. Even though this type of inheritance is not used widely but is significant to some applications in HAS-A relation.

Question Section

In the end, let's test what we have learned today. A code segment is given below, answer the following questions.

class Alpha
{
    private:
        int p = 1;
        int func_p();
    public:
        int t;
        int print(){return p;}
    protected:
        int rat;
        void fry(){cout<<"HI";}
};

class Beta : private Alpha
{
    private:
        int send;
    public:
        int t;
        void fry()
        { cout<<"BYE"<<print();
          Alpha::fry();
        }
};


int main()
{
    Alpha a;
    Beta b;
    return 0;
}

Question 1

What would a.fry() return if written in the main?

HI
BYEHI
BYE1HI
Error
It will give an error because fry() is a protected member of Alpha.

Question 2

What would b.fry() return if written in the main?

HI1BYE
BYE
BYE1HI
HIBYE
fry() has been overridden in class Beta so it would display 'BYE' then the value of p using the print() function and then alpha::fry() which prints HI.

With this article at OpenGenus, you must have the complete idea of Private Inheritance in C++. Enjoy.