Inheritance
It’s a common saying. It suggests that we carry over some of the traits of our parents. Not only that we carry over their traits, but also, their belongings. They give us whatever they have except for a few things, which they treat as personnel or private to them. Except for these few, everything else, by default, falls in our lap. They serve us as a ‘base’ for our growth. Apart from what we get from our parents in legacy, we also have some personnel traits and acquire our own belongings, which prove to be an extension to the subtle base our parents provide. This is the phenomenon of INHERITANCE. In this whole process one unique feature that comes out is that we as inheritors are not required to work for what our parents have acquired - we simply ‘extend’ it. However at the application point the effect is of our possessing both - into our account - what our parents had and what we have. In OOPS this concept is followed, as it is, by extending classes. Inheritance is a real-life concept of deriving something more specific from a generalised existing thing, children have their own mental, physical and spiritual traits but they also inherit the features of their parents. Inheritance, as a mechanism of extending classes, involves deriving a new class from an old one. (existing one). The existing/old class is referred to as base class and the new one is known as the derived class. An example of inheritance is shown in fig lh1.
Introduction“Father or Mother is reflected in a child……”
The direction of arrow in figure lh1 should not be a source of confusion for the reader. Some texts show the arrow pointing from base class to derived class, while other texts show it in reverse order (representing “inherited from “relationship). The derived class inherits some or all of the traits from the base class.
Why Inheritance?
Inheritance truly supports REUSABILITY feature of Object Oriented Programming (OOP). If a class has been tested, debugged and used many times, then the effort of developing and testing the class again can be saved by making use of same class. If changes are required, programmers can derive another class from already existing one and make necessary changes in the derived of class. A class “fun” developed by Tom can be used by his friends X, Y, Z, A, B and so on (of course! only as long as Tom is willing to do share).
Different Types of Inheritance
Single Inheritance
A derived class has only one base class. (see figure lh2).
A class with several base classes is known as multiple inheritance (see figure lh33)
Class C inherits from both A and B
Hierarchical Inheritance
The mechanism of deriving a class from another ‘derived’ class is known as ‘multilevel’ inheritance (see figure lh5).
Hybrid Inheritance
This form of inheritance combines two or more forms of inheritance (see figure lh6)
Defining Derived Classes; Visibility Modes
In order to define a class having name derived-class-name from a class having name base-class-name, the following syntax is used
class derived-class-name : visibility-mode base-class-name
{
// members of derived class
};
The colon indicates that the derived-class-name has been derived from base-class-name.
It is important to learn about visibility modes while inheriting from a class. REMEMBER THAT PRIVATE DATA MEMBERS OF BASE CLASS WILL NOT BE INHERITED IN ANY CASE. When a class is ‘privately inherited’, its effect is that all public members of base class become private in the derived class, such that they are inaccessible to the objects of the derived class. On the other hand, when a class is publicly inherited into another class, the public members of base class remain public in the derived class, such that they are accessible to the objects of derived class. The syntax illustration is given below: -
class ABC: private XYZ /*private derivation */
{
members of ABC
};
Class ABC : public XYZ /* public derivation */
{
members of ABC
};
Consider the example of public inheritance given below:
class base
{
int a;
public :
int b;
void get_ab();
int return_a();
void show_a();
};
void base : : get_ab()
{
cin >>a >>b;
}
int base :: return_a()
{
return a;
}
void base :: show_a ()
{ cout << “\n a = “<< a; }
class derived : public base
{ int c;
public :
void add ();
void display ();
};
void derived :: add()
{
c= return_a() +b;
}
void derived :: display()
{
cout << “\n a = “<
cout << “\n b = “<
cout << “\n c = “<
}
void main ()
{
derived D;
D.get_ab(); /*public members of base class are */
D.add(); /* public members of derived class now */
D.show_a();
D.display ();
D.b= 35; /* b is also available as public member in derived*/
D.add();
D.display ();
}
The memory map of class derived is as shown in figure lh7
Let us now modify the earlier example a bit (though it will make a big change!) by inheriting the derived class privately. Notice the consequent changes design carefully
class base
{
int a;
public;
int b;
void get_ab( );
int return_a( );
void show_a( );
};
void base :: get_ab( )
{
cin >> a>>b;
}
void base :: return_a( )
{
return a;
}
void base :: show_a()
{
cout << “\n a =” <
}
};
class derived : private base
{
int c;
public;
void add ( );
void display ( );
};
void derived :: add ( )
{
get_ab ( );
c = return_a( ) + b;
}
void derived :: display ( )
{
cout << “\n a = “<
cout << “\n b = “<
cout << “\n c = “<
}
void main ( )
{
derived D;
D.add( ); /* D.get_ab ( ) is not allowed as get_ab( ) is a
private data member of derived class */
D.display ( );
}
Observe the effect of changing visibility mode to private. The main function cannot have the following statements: -
D.show_a( ); /*not allowed */
D.b = 35;
This is simply because show_a( ) and b are also private members of derived as is et_ab( ). The memory map of derived class is shown in fig.
The memory map of class derived is as shown in figure lh8
A major problem that remains unsolved is how to inherit a private data member, if it is needed in derived class. The ‘private’ label does not allow to break the walls of encapsulation whereas making such a data member ‘public’ would make it accessible to outside world besides imparting it inheritance capability.
The answer is ‘protected’ data member. The visibility label ‘protected’ ensures that the members declared under it are accessible to the derived class through inheritance. Further, protected members cannot be accessed by the functions outside the class. In a way, they combine the functionality of private and public members into one label. It is important to learn that behavior of protected data members in derived class depends upon visibility mode of inheritance.
The following example shows the use of protected visibility label:
# include
class base
{
protected ;
int a;
public;
int b;
void get_ab ( )
{
cin >> a>>b; }
}
class derived : private base
{
int c;
public:
void add ( )
{
get_ab( ) /* get_ab( ) is now private member of derived class */
c = a + b;
}
void display ( )
{
cout << “\n a = ” <
cout << “\n b = ” <
cout << “\n c = ” <, c;
}
};
void main ( )
{ derived D;
D.add ( );
D.display ( );
}
In the given example, the protected member ‘a’ became private in derived class. But it cannot be referred directly in main. Further, the function get_ab( ) can be completely removed by accepting the input for a and b in the add ( ) function itself. When using ‘protected’ visibility label, inheritance should be public if we expect more classes to be derived from the ‘derived’ class. (so that the protected member lands as protected in the derived class). In case the inheritance is not needed further after derived class, it is advisable to inherit privately. That is why, the last example uses private inheritance.
The table given in figure lh9 summarizes the inheritance rules: -