CH 5
CH 5
Inheritance
Introduction
• The mechanism of deriving a new class from an old one is called inheritance(or derivation).
• The old class is referred to as the base class and the new one is called the derived class or subclass.
• The derived class inherits some or all of the traits from the base class.
• A class can also inherit properties from more than one class or from more than one level.
• A derived class with only one base class, is called single inheritance.
• One with several base classes is called multiple inheritance.
• The traits of one class may be inherited by more than one class is known as hierarchical inheritance.
• The mechanism of deriving a class from another ‘derived class’ is known as multilevel inheritance.
• Following figure shows various forms of inheritance –
Defining derived classes-
• A derived class can be defined as specifying its relationship with the base class in addition to its own details.
• The general form of defining a derived class is-
• The colon indicates that the derived-class-name is derived from the base-class-name .
• The visibility-mode is optional, if present, may be either private or public.
• The default visibility-mode is private.
e.g.
1. When a base class is privately inherited by a derived class, ’public members’ of the base class become ‘private
members’ of the derived class and therefore the public members of the base class can only be accessed by the
member functions of the derived class. They are inaccessible to the objects of the derived class.
Remember : a public member of a class can be accessed by its own objects using the dot operator. The result is that no
member of the base class is accessible to the objects of the derived class.
2. When the base class is publicly inherited, ‘public members’ of the base class become ‘public members’ of the derived
class become ‘public members’ of the derived class and therefore they are accessible to the objects of the derived class.
• In both the cases private members are not inherited and therefore, the private members of a base class will never
become the members of its derived class.
• In inheritance, some of the base class data elements and member functions are ‘inherited’ into the derived class. We
can add our own data and member functions and thus extend the functionality of the base class.
Single inheritance
Program: Single inheritance : Public
#include<iostream>
using namespace std;
class B
{
int a; //private; not inheritable
public:
int b; // public; ready for inheritable
void set_ab();
int get_a(void);
void show_a(void);
};
class D : public B // public derivation
{
int c;
public:
void mul(void);
void display(void);
};
void B :: set_ab(void)
{
a=5;
b=10;
}
int B :: get_a()
{
return a;
}
void B :: show_a()
{
cout<<"a="<<a<<"\n";
}
void D :: mul()
{
c=b*get_a();
}
void D :: display()
{
cout<<"a="<<get_a()<<"\n";
cout<<"b="<<b<<endl;
cout<<"c="<<c<<endl<<endl; Output
} a=5
int main() a=5
{ b=10
D d; c=50
d.set_ab();
d.mul(); a=5
d.show_a(); b=20
d.display(); c=100
d.b=20;
d.mul();
d.display();
• The class D is a public derivation of the base class B. Therefore, D inherits all the public members of B and retains
their visibility.
• Thus a public member of the base class B is also a public member of the derived class D.
• The private members of the B cannot be inherited by D.
• The class will have more members than what it contains at the time of declaration as shown in fig. below-
• Imp: Although the data member a is private in B and cannot be inherited , objects of D are able to access it through an
inherited member function of B.
• Let us now consider the case of private derivation.
In private derivation, the public members of the base class become private members of the derived class. Therefore, the
objects of D can not have direct access to the public member functions of B.
Program: Single inheritance : Private
#include<iostream>
using namespace std;
class B
{
int a; //private; not inheritable
public:
int b; // public; ready for inheritable
void get_ab();
int get_a(void);
void show_a(void);
};
class D : private B // public derivation
{
int c;
public:
void mul(void);
void display(void);
};
void B :: get_ab(void)
{
cout<<"Enter the values for a and b=";
cin>>a>>b;
}
int B :: get_a()
{
return a;
}
void B :: show_a()
{
cout<<"a="<<a<<"\n";
}
void D :: mul()
{
Output
get_ab();
c=b*get_a(); //'a' cannot be used directly Enter the values for a
} and b= 3 4
void D :: display() a=3
{ b=4
show_a(); // output value of 'a’ c=12
cout<<"b="<<b<<endl;
cout<<"c="<<c<<endl<<endl; Enter the values for a
}
and b=5 6
int main()
{ a=5
D d; b=6
d.mul(); c=30
d.display();
d.mul();
d.display();
return 0;
}
• The statements such as
d.get_ab();
d.get_a();
d.show_a();
get_ab(), get_a(), show_a() are private so it will not work, these functions can be used inside mul() and display () like
the normal functions.
Making a private member inheritable
• C++ provides the third visibility modifier, protected, which serve a limited purpose in inheritance.
• A member declared a protected is accessible by the member functions within its class and any class immediately
derived from it, it cannot be accessed by the functions outside these two classes.
• A class can now use all the three visibility modes as shown in below.
1. When a protected member is inherited in public mode, it becomes protected in the derived class too and therefore
is accessible by the member functions of the derived class. It is also ready for further inheritance.
2. A protected member, inherited in the private mode derivation, becomes private in the derived class. Although it
is available to the member functions of the derived class, it is not available for further inheritance.
• Following figure shows, representation for the two levels of derivation-
Hierarchical
Inheritance
Multiple
Inheritance
• It is also possible to inherit a base class in protected mode. In protected derivation, both the public and protected
members of the base class become protected members of the derived class.
• Following table summarizes how the visibility of base class members undergoes modification in all the three types of
derivation.
• A simplified view of access control to the members of a class is shown in fig. below-
Multilevel Inheritance
• As shown in figure below A serves as a base class for the derived class B, which in turn serves as a base class for the derived
class B.
• The class B is known as intermediate base class since it provides a link for the inheritance between A and C.
• The chain ABC is known as inheritance path.
• The derived class with multilevel inheritance is declared as follows-
class A // base class class B: public A // B derived from A class C:public B // C derived from B
{ { {
…….. …….. …….
} } }
Program:
#include<iostream>
using namespace std;
class student
{
protected:
int roll_number;
public:
void get_number(int);
void put_number(void);
};
void student :: get_number(int a)
{
roll_number=a;
}
void student :: put_number()
{
cout<<"Roll number=>"<<roll_number<<endl;
}
class test : public student // first level inheritance
{
protected:
float sub1;
float sub2;
public:
void get_marks(float, float);
void put_marks(void);
};
void test :: get_marks(float x, float y)
{
sub1=x;
sub2=y;
}
void test :: put_marks()
{
cout<<"Marks in subject 1=>"<<sub1<<endl;
cout<<"Marks in subject 2=>"<<sub2<<endl;
}
class result : public test // second level inheritance
{
float total;
public:
void display(void);
};
void result :: display(void)
{
total=sub1+sub2;
put_number();
put_marks();
cout<<"Total=>"<<total<<endl;
}
int main()
{
result student1;
student1.get_number(12); student1.get_marks(80.0,67.5); student1.display(); return 0;}
int main()
{
result student1;
student1.get_number(12);
student1.get_marks(80.0,67.5);
student1.display();
return 0;
}
Output:
Roll number=>12
Marks in subject 1=>80
Marks in subject 2=>67.5
Total=>147.5
• The class result after inheritance from ‘ grandfather’ through ‘father’ , would contain the following members-
Multiple inheritance
• A class can inherit the attributes of two or more classes as shown in fig below- This is known as multiple inheritance.
• Multiple inheritance allows us to combine the features of several existing classes as a starting point for defining new classes.
• The syntax of a derived class with multiple base classes is as follows-
class D : visibility B-1, visibility B-2…..
{
…….
……. (body of D)
…….
};
Where, visibility may be either public or private. The base classes are separated by commas.
Program:
#include<iostream>
using namespace std;
class M1
{
protected:
int m;
public:
void get_m(int);
};
class N1
{
protected:
int n;
public:
void get_n(int);
};
void N1 :: get_n(int y)
{
n=y;
}
void P :: display(void)
{
cout<<"m=>"<<m<<endl;
cout<<"n=>"<<n<<endl;
cout<<"m*n=>"<<m*n<<endl;
}
int main()
{
P p;
p.get_m(10);
p.get_n(20);
p.display();
return 0;
}
Output:
m=>10
n=>20
m*n=>200
• The derived class P , as declared above contain all the members of M and N in addition with its own members as
shown in below-
Ambiguity resolution in inheritance
• Consider the following two classes-
class M
{
public:
void display(void)
{
cout<<“Class M “<<endl;
}
};
class N
{
public:
void display(void)
{
cout<<“Class MN“<<endl;
}
};
• Which display() function is used by the derived class when we inherit these two classes?
• we can solve this problem by defining a named instance within the derived class, using the class resolution operator
with the function as shown below-
class A
{
public:
void display()
{
cout<<“A=>”<<endl;
}
};
class B : public A
{
public:
void display()
{
cout<<“B=>”<<endl;
}
};
• In this case, the function in the derived class overrides the inherited function and therefore, a simple call to
display() by B type object will invoke function defined in B only.
• However, we may invoke the function defined in A by using scope resolution operator to specify the class.
e.g.
int main()
{
B b; //derived class object
b.display(); // invokes display() in B
b.A :: display(); // invokes display() in A
b.B :: display(); // invokes display() in B
return 0;
}
• Another example could be the classification of accounts in a commercial bank as shown below-
Hybrid inheritance-
• There could be situations where we need to apply two or more types of inheritance to design a program.
e.g.
Consider a case of processing the students results. Assume that we have to give weightage for sports before finalizing the
results. The weightage for sports is stored in a separate class called sports as shown in fig below-
Program:
#include<iostream>
• The 'child' has two direct base classes ‘parent1’ and ‘parent2’ which themselves has a common base class
‘grandparent’.
• The child inherits the traits of ‘grandparent’ via two separate paths. It can also be inherit directly as shown by the
broken line.
• The grandparent is sometimes referred to as ‘INDIRECT BASE CLASS’.
• Now, the inheritance by the child might cause some problems. All the public and protected members of ‘grandparent’
are inherited into ‘child’ twice, first via ‘parent1’ and again via ‘parent2’.
• This means, ‘child’ would have duplicate sets of the members inherited from ‘grandfather’.
• This introduces ambiguity and should be avoided.
• The duplication of inherited members due to these multiple paths can be avoided by making the common base
class(ancestor class) as virtual base class while declaring the direct or intermediate base classes as shown below-
class g_parent
{
//Body
};
Program:
#include<iostream>
using namespace std;
class student
{
protected:
int roll_number;
public:
void get_number(int a)
{
roll_number=a;
}
void put_number(void)
{
cout<<"Roll no=>"<<roll_number<<endl;
}
};
class test : virtual public student
{
protected:
float part1, part2;
public:
void get_marks(float x, float y)
{
part1=x;
part2=y;
}
void put_marks(void)
{
cout<<"Marks obtained=>"<<endl;
cout<<"Part1=>"<<part1<<endl;
cout<<"Part2=>"<<part2<<endl;
}
};
return 0;
}
Output:
Roll no=>123
Marks obtained=>
Part1=>89.5
Part2=>93.5
Sports weightage=>8
Total score=>191
Constructors in derived classes
• Imp. Note: 1. As long as no base class constructor takes any argument, the derived class need not have a constructor
function.
2. However, if any base class contains a constructor with one or more arguments, then it is mandatory for the derived class
to have a constructor and pass the arguments to the base class constructors.
• When both the derived and base classes contain constructors, the base constructor is executed first and then the
constructor in the derived class is executed.
• In case of multiple inheritance, the base classes are constructed in the order in which they appear in the declaration of
the derived class.
• Similarly, in a multilevel inheritance, the constructors will be executed in the order of inheritance.
• Since the derived class takes the responsibility of supplying initial values to its base classes, we supply the initial
values that are required by all the classes together, when a derived class object is declared.
• The constructor of the derived class receives the entire list of values as its arguments and passes them on to the base
constructors in the order in which they are declared in the derived class.
• The base constructors are called and executed before executing the statements in the body of the derived constructor.
• The general form of defining a derived constructor is-
baseN(arglistN),
{
Body of derived constructor
}
The header line of derived-constructor function contains two parts separated by a colon(:).
1. The first part provides the declaration of the arguments that are passed to the derived-constructor.
2. The second part lists the function calls to the base constructors.
D(int a1, int a2, float b1, float b2, int d1):
A(a1,a2), // call to constructor A
B(b1,b2) // call to constructor B
{
d=d1; // executes its own body
}
• A(a1,a2) invokes the base constructor A() and B(b1,b2) invokes another base constructor B().
• The constructor D() supplies the values for these four argument. In addition, it has one argument of its own. The
constructor D() has a total of five arguments.
• D() may be invoked as follows-
………
D objD(5, 10, 3.5, 6.7, 30);
……..
These values are assigned to various parameters by the constructors D() as follows-
5 a1
10 a2
3.5 b1
6.7 b2
30 d1
• The constructor for virtual base classes are invoked before any nonvirtual base classes .
• If there are multiple virtual base classes, they are invoked in the order in which they are declared.
• Any non-virtual bases are then constructed before the derived class constructor is executed as shown in below table-
Program:
#include<iostream>
using namespace std;
class alpha
{
int x;
public:
alpha(int i)
{
x=i;
cout<<"alpha initialized\n";
}
void show_x(void)
{
cout<<"x="<<x<<endl;
}
};
class beta
{
float y;
public:
beta(float j)
{
y=j;
cout<<"beta initialized\n";
void show_y(void)
{
cout<<"y="<<y<<endl;
}
};
return 0;
}
Output:
beta initialized
alpha initialized
gamma initialized
x=5
y=10.75
m=20
n=30
Note: beta is initialized first, although it appears second in the derived constructor. This is because it has been declared first
in the derived class header line. Also note that alpha(a) and beta(b) are function calls. Therefore, the parametes should not
include types.