2. Private inheritance in C++ is an important subject and should be studied
thoroughly in order to understand different nuances of C++. The way private
inheritance is done is as follows:
Class Derived : private Base{
…..
…..
};
From a programmer’s point of view it means that the public and the protected
members of the Base class which will be inherited by the Derived class will become
private in the Derived class.
However there is a greater significance of private inheritance in C++ from an
Object Oriented Designer’s perspective. Private Inheritance actually means that we
are not inheriting the interface of the Base class, but we are inheriting the
implementation. It means that in the derived class, we can create member functions
which can be implemented in terms of the Base class functions. So it is something
like the Derived class HAS the Base class and this is also known as Composition.
One very useful application of private inheritance is in the Adapter Pattern
specifically in the Class Adapter pattern (and not the Object Adapter).
Another aspect of private inheritance I must add here. Normally in any OOPS, we
can pass an object of a derived class in a function which takes a type of the Base
class as a parameter. This is possible because as we say in UML, the subclass is
of type SuperClass. Or Subclass IS A SuperClass. But in case of Private
Inheritance, we cannot do that because the derived class does not become a subtype
of the base class. Hence in case we pass an Object of a privately derived subclass
to a method which expects an Object of type Superclass, the compiler will not be
able to do the automatic type conversion and will throw a Compile time error. Lets
see the following example to understand this.
#include <iostream>
#include <string>
using namespace std;
class Fruit{
private:
string color;
int calory;
protected:
bool toBePeeled;
public:
Fruit():color("RED"), calory(100), toBePeeled(false){
}
4. //Human can eat any fruit
void eatFruit(Fruit& fruit){
string text;
if(fruit.isToBePeeled()){
text = "after peeling it";
}
else{
text = "without peeling it";
}
cout<<"I have eaten a " <<fruit.getColor()<<" colored fruit "
<<text<<" and taken in "<<fruit.getCalory()<<" calories "<<endl;
}
};
int main() {
Human me;
Orange orange;
//i am eating an Orange. As orange is privately derived. Hence the passed
object will not be automatically converted to Fruit. hence it will give error...
me.eatFruit(orange);//error
Banana banana;
banana.setColor("YELLOW");
banana.setCalory(500);
me.eatFruit(banana); //okay
return 0;
}
As shown in the above example, Orange has been privately derived from Fruit. Hence
Orange cannot be considered as a subtype of Fruit. As a result, in the eatFruit method
we cannot pass an orange object in place of the Fruit data type. On the other hand Banana
has been publicly derived from Fruit. Hence Banana IS A Fruit. And hence we can pass a
banana object as a parameter of the eatFruit method.
Now let us see a practical use of private inheritance to implement Adapter Pattern as
described in the Gang of Four book. There are two ways through which the adapter pattern
can be implemented -
● Class Adapter
● Object Adapter
In class adapter, the Adapter class inherits publicly from the Target class and privately from
the Adaptee class as shown below:
5. So the Adapter class inherits the interface of the Target (here Request()), but it implements
the functionality using the privately inherited Adaptee’s functions (here specificRequest). So
the client calls the Adapter’s interface which in turn calls Adaptee’s functions.