Unit Ii Inheritance & Polymorphism
Unit Ii Inheritance & Polymorphism
Unit Ii Inheritance & Polymorphism
Table of Contents
Base Classes and Derived Classes..............................................................................2
Types of Inheritance:..................................................................................................... 4
Single Inheritance...................................................................................................... 4
Multiple Inheritance................................................................................................... 6
Hierarchical Inheritance.............................................................................................. 8
Multilevel Inheritance............................................................................................... 11
Hybrid (Virtual) Inheritance....................................................................................... 13
Casting Class pointers and Member Functions.........................................................14
Overriding................................................................................................................. 16
Public, Protected and Private Inheritance.................................................................19
Private Inheritance...................................................................................................... 19
Accessibility in Private Inheritance..........................................................................20
Public Inheritance....................................................................................................... 20
Accessibility in Public Inheritance........................................................................... 20
Protected Inheritance................................................................................................... 20
Accessibility in Protected Inheritance.......................................................................21
Constructors and Destructors in derived Classes.....................................................21
Implicit Derived-Class Object to Base Class.............................................................22
COMPOSITION VS INHERITANCE:..............................................................................23
virtual functions........................................................................................................ 24
Virtual Table:............................................................................................................. 26
This Pointer............................................................................................................... 26
Abstract Base Classes and Concrete Classes...........................................................28
Virtual Destructors................................................................................................... 31
Dynamic Binding...................................................................................................... 33
Base Classes and Derived Classes Protected Members Casting Class pointers and Member
Functions Overriding Public, Protected and Private Inheritance Constructors and
Destructors in derived Classes Implicit Derived Class Object To Base Class Object
Conversion Composition Vs. Inheritance Virtual functions This Pointer Abstract Base
Classes and Concrete Classes Virtual Destructors Dynamic Binding.
Program:
#include<iostream.h>
class student
{
public:
int rno;
//float per;
char name[20];
void getdata()
{
cout<<"Enter RollNo :- \t";
cin>>rno;
cout<<"Enter Name :- \t";
cin>>name;
}
};
class marks : public student
{
public:
int m1,m2,m3,tot;
float per;
void getmarks()
{
cout<<"Enter Marks 1 :- \t";
cin>>m1;
cout<<"Enter Marks 2 :- \t";
cin>>m2;
cout<<"Enter Marks 2 :- \t";
cin>>m3;
cout<<"Roll Not \t Name \t Marks1 \t marks2 \t Marks3 \t Total \t Percentage";
cout<<rno<<"\t"<<name<<"\t"<<m1<<"\t"<<m2<<"\t"<<m3<<"\t"<<tot<<"\t"<<per;
}
};
void main()
{
student std;
std.getmarks();
}
A derived class can access all the non-private members of its base class. Thus base-class
members that should not be accessible to the member functions of derived classes should be
declared private in the base class.
We can summarize the different access types according to who can access them in the following
way:
Access
Public
protected
private
Same class
Yes
yes
yes
Derived classes
Yes
yes
no
Outside classes
Yes
no
no
Types of Inheritance:
There are 5 different types of Inheritance. Namely,
1. Single Inheritance
2. Multiple Inheritance
3. Hierarchical Inheritance
4. Multilevel Inheritance
5. Hybrid Inheritance (also known as Virtual Inheritance)
Single Inheritance
In this type of inheritance one derived class inherits from only one base class. It is the most
simplest form of Inheritance.
Program:
#include<iostream.h>
class student
{
public:
int rno;
//float per;
char name[20];
void getdata()
{
cout<<"Enter RollNo :- \t";
cin>>rno;
cout<<"Enter Name :- \t";
cin>>name;
}
};
class marks : public student
{
public:
int m1,m2,m3,tot;
float per;
void getmarks()
{
cout<<"Enter Marks 1 :- \t";
cin>>m1;
cout<<"Enter Marks 2 :- \t";
cin>>m2;
cout<<"Enter Marks 2 :- \t";
cin>>m3;
In this type of inheritance a single derived class may inherit from two or more than two base
classes.
Hierarchical Inheritance
In this type of inheritance, multiple derived classes inherits from a single base class.
10
11
Multilevel Inheritance
In this type of inheritance the derived class inherits from a class, which in turn inherits from
some other class. The Super class for one, is sub class for the other.
12
void put_mks();
};
void Test::get_mks(float a,float b)
{
sub1=a;sub2=b;
}
void Test::put_mks()
{
cout<<"marks in sub1= "<<sub1<<"\n";
cout<<"marks in sub2= "<<sub2<<"\n";
}
class Result:public Test
{
float total;
public:
void display();
};
void Result::display()
{
total=sub1+sub2;
put_num();
put_mks();
cout<<"total = "<<total<<"\n";
}
void main()
{
int r;
float s1,s2;
Result obj;
clrscr();
cout<<"enter the Roll no of Student\n";
cin>>r;
cout<<"\nenter the marks of the student in 2 subject\n";
cin>>s1>>s2;
obj.get_num(r);
obj.get_mks(s1,s2);
obj.display();
getch();
}
13
Hybrid (Virtual) Inheritance
14
protected:
public:
void getd()
{
cout<<"Enter d value:";
cin>>d;
}
};
class D:public B,public C
{
protected:
public:
void result()
{
getab();
getc();
getd();
e=a+b+c+d;
cout<<"\n Addition is :"<<e;
}
};
void main()
{
clrscr();
D d1;
d1.result();
getch();
}
15
16
float f;
};
int main () {
base b;
derived d;
base *pointer_to_base;
derived *pointer_to_derived;
pointer_to_base=&d;
pointer_to_derived=static_cast<derived*>(&b);
}
Overriding
1. Defining a function in the derived class with same name as in the parent class is
called overriding. In C++, the base class member can be overridden by the derived
class function with the same signature as the base class function.
2. Method overriding is used to provide different implementations of a function so that a
more specific behavior can be realized.
Overriding vs. overloading
Overloading means having methods with same name but different signature.
Overriding means rewriting the virtual method of the base class.
Explain the problem with overriding functions.
Overriding of functions occurs in Inheritance. A derived class may override a base class member
function. In overriding, the function names and parameter list are same in both the functions.
17
18
Program:
class A
{
int a;
public:
A()
{
a = 10;
}
void show()
{
cout << a;
}
};
class B: public A
{
int b;
public:
B()
{
b = 20;
}
void show()
{
cout << b;
19
}
};
int main()
{
A ob1;
B ob2;
ob2.show(); // calls derived class show() function. o/p is 20
return 0;
}
Private Inheritance
The Public and protected members of Base class become private members of the derived class.
class base
{
.... ... ....
};
class derived : private base
{
.... ... ....
};
20
private
protected
public
yes
yes
yes
no
yes
yes
no
no
no
Public Inheritance
All the public members and protected members are inherited as public and protected
respectively.
class base
{
.... ... ....
};
class derived : public base
{
.... ... ....
};
private
protected
public
yes
yes
yes
no
yes
yes
no
no
yes
Protected Inheritance
Public and Protected members are derived as protected members.
21
class base
{
.... ... ....
};
class derived : protected base
{
.... ... ....
};
private
protected
public
yes
yes
yes
no
yes
yes
no
no
no
22
}
~Base ( )
{
cout << "Inside Base destructor" << endl;
}
};
class Derived : public Base
{
public:
Derived ( )
{
cout << "Inside Derived constructor" << endl;
}
~Derived ( )
{
cout << "Inside Derived destructor" << endl;
}
};
void main( )
{
Derived x;
}
In the code above, when the object "x" is created, first the Base class constructor is
called, and after that the Derived class constructor is called. Because the Derived class inherits
from the Base class, both the Base class and Derived class constructors will be called when a
Derived class object is created.
When the main function is finished running, the object x's destructor will get called first, and
after that the Base class destructor will be called.
So, here is what the output of the code above would look like:
Output:
Inside Base constructor
Inside Derived constructor
Inside Derived destructor
Inside Base destructor
23
2. Derived class has members corresponding to the entire base classs members
3. Derived-class has more members than the base-class object
4. Base-class can be assigned a derived-class
5. Base-class object cannot be treated as a derived-class object
Object Conversion
Mixing base and derived class pointers and objects
Referring to a base-class object with a base-class pointer
Allowed
Referring to a derived-class object with a derived-class pointer
Allowed
Referring to a derived-class object with a base-class pointer
Possible syntax error
Code can only refer to base-class members, or syntax error
Referring to a base-class object with a derived-class pointer
Syntax error
The derived-class pointer must first be cast to a base-class pointer
COMPOSITION VS INHERITANCE:
Is a relationships are supported by public inheritance. In has a relationship, a class may
have other classes as members. Such relationships create new classes by composition of
existing classes.
Eg:
Given the classes Employee, BirthDate and TelephoneNumber, it is improper to say
that an Employee is a BirthDate or that an Employee is a TelephoneNumber.
But it is certainly appropriate to say that an Employee has a BirthDate and that an Employee has
a TelephoneNumber.
Program:
class X
{
int i;
public:
X()
{
i = 0;
}
void set(int ii)
{
i = ii;
}
24
int read()
{
return i;
}
int permute()
{
return i = i * 47;
}
};
class Y {
int i;
public:
X x; // Embedded object
Y()
{
i = 0;
}
void f(int ii)
{
i = ii;
}
int g()
{
return i;
}
};
int main()
{
Y y;
y.f(47);
y.x.set(37); // Access the embedded object
}
virtual functions
1. Virtual function is a member function that is declared within a base class and redefined
by a derived class. To create virtual function, precede the functions declaration in the
base class with the keyword virtual.
2. When a class containing virtual function is inherited, the derived class redefines the
virtual function to suit its own needs.
25
3. Base class pointer can point to derived class object. In this case, using base class pointer
if we call some function which is in both classes, then base class function is invoked. But
if we want to invoke derived class function using base class pointer, it can be achieved by
defining the function as virtual in base class, this is how virtual functions support runtime
polymorphism.
Consider following program code:
Class A
{
int a;
public:
A()
{
a = 1;
}
virtual void show()
{
cout <<a;
}
};
Class B: public A
{
int b;
public:
B()
{
b = 2;
}
virtual void show()
{
cout <<b;
}
};
int main()
{
A *pA;
B oB;
pA = &oB;
pA->show();
return 0;
}
Output is 2 since pA points to object of B and show() is virtual in base class A.
26
Virtual Table:
A virtual table is a mechanism to perform dynamic polymorphism i.e., run time binging. Virtual
table is used to resolve the function calls at runtime. Every class that uses virtual functions is
provided with its own virtual functions.
Every entry in the virtual table is a pointer that points to the derived function that is accessible by
that class. A hidden pointer is added by a compiler to the base class which in turn calls *_vptr
which is automatically set when an instance of the class is created and it points to the virtual
table for that class.
This Pointer
The this pointer is passed as a hidden argument to all nonstatic member function calls and is
available as a local variable within the body of all nonstatic functions. this pointer is a constant
pointer that holds the memory address of the current object. this pointer is not available in
static member functions as static member functions can be called without any object (with class
name).
For a class X, the type of this pointer is X* const. Also, if a member function of X is declared
as const, then the type of this pointer is const X *const (see this GFact)
Following are the situations where this pointer is used:
1) When local variables name is same as members name
#include<iostream>
using namespace std;
/* local variable is same as a member's name */
class Test
{
private:
int x;
public:
void setX (int x)
{
// The 'this' pointer is used to retrieve the object's x
// hidden by the local variable 'x'
this->x = x;
}
void print()
{
cout << "x = " << x << endl;
}
};
int main()
{
Test obj;
int x = 20;
27
obj.setX(x);
obj.print();
return 0;
}
Output:
x = 20
For constructors, initializer list can also be used when parameter name is same as members
name.
2) To return reference to the calling object
/* Reference to the calling object can be returned */
Test& Test::func ()
{
// Some processing
return *this;
}
When a reference to a local object is returned, the returned reference can be used to chain
function calls on a single object.
#include<iostream>
using namespace std;
class Test
{
private:
int x;
int y;
public:
Test(int x = 0, int y = 0)
{
this->x = x;
this->y = y;
}
Test &setX(int a)
{
x = a;
return *this;
}
Test &setY(int b)
{ y = b;
return *this;
}
void print()
{
cout << "x = " << x << " y = " << y << endl;
}
};
28
int main()
{
Test obj1(5, 5);
// Chained function calls. All calls modify the same object
// as the same object is returned by reference
obj1.setX(10).setY(20);
obj1.print();
return 0;
}
Output:
x = 10 y = 20
};
double length;
// Length of a box
double breadth;
// Breadth of a box
double height;
// Height of a box
29
The purpose of an abstract class (often referred to as an ABC) is to provide an appropriate base
class from which other classes can inherit.
Abstract classes cannot be used to instantiate objects and serves only as an interface. Attempting
to instantiate an object of an abstract class causes a compilation error.
Thus, if a subclass of an ABC needs to be instantiated, it has to implement each of the virtual
functions, which means that it supports the interface declared by the ABC.
Failure to override a pure virtual function in a derived class, then attempting to instantiate objects
of that class, is a compilation error.
Classes that can be used to instantiate objects are called concrete classes.
Abstract Class Example:
Consider the following example where parent class provides an interface to the base class to
implement a function called getArea():
#include <iostream>
using namespace std;
// Base class
class Shape
{
public:
// pure virtual function providing interface framework.
virtual int getArea() = 0;
void setWidth(int w)
{
width = w;
}
void setHeight(int h)
{
height = h;
}
protected:
int width;
int height;
};
// Derived classes
class Rectangle: public Shape
{
30
public:
int getArea()
{
return (width * height);
}
};
class Triangle: public Shape
{
public:
int getArea()
{
return (width * height)/2;
}
};
int main(void)
{
Rectangle Rect;
Triangle Tri;
Rect.setWidth(5);
Rect.setHeight(7);
// Print the area of the object.
cout << "Total Rectangle area: " << Rect.getArea() << endl;
Tri.setWidth(5);
Tri.setHeight(7);
// Print the area of the object.
cout << "Total Triangle area: " << Tri.getArea() << endl;
return 0;
}
When the above code is compiled and executed, it produces the following result:
Total Rectangle area: 35
Total Triangle area: 17
You can see how an abstract class defined an interface in terms of getArea() and two other
classes implemented same function but with different algorithm to calculate the area specific to
the shape.
31
Virtual Destructors
1. In C++ a destructor is generally used to deallocate memory and do some other
cleanup for a class object and its class members whenever an object is destroyed.
2. Destructors are distinguished by the tilde, the ~ that appears in front of the
destructor name.
3. In order to define a virtual destructor, all you have to do is simply add the keyword
virtual before the tilde symbol.
The need for virtual destructors in C++ is best illustrated by some examples. Lets start by going
through an example that does not use virtual destructors, and then we will go through an example
that does use virtual destructors.
Example without a Virtual Destructor:
#include iostream.h
class Base
{
public:
Base(){ cout<<"Constructing Base";}
// this is a destructor:
~Base(){ cout<<"Destroying Base";}
};
class Derive: public Base
{
public:
Derive(){ cout<<"Constructing Derive";}
~Derive(){ cout<<"Destroying Derive";}
};
void main()
{
Base *basePtr = new Derive();
delete basePtr;
}
The output after running the code above would be:
Constructing Base
Constructing Derive
Destroying Base
32
Based on the output above, we can see that the constructors get called in the appropriate order
when we create the Derive class object pointer in the main function.
But there is a major problem with the code above: the destructor for the "Derive" class does not
get called at all when we delete basePtr.
Well, what we can do is make the base class destructor virtual, and that will ensure that the
destructor for any class that derives from Base (in our case, its the "Derive" class) will be called.
Example with a Virtual Destructor:
So, the only thing we will need to change is the destructor in the Base class and heres what it
will look like note that we highlighted the part of the code where the virtual keyword has been
added in red:
class Base
{
public:
Base(){ cout<<"Constructing Base";}
// this is a virtual destructor:
virtual ~Base(){ cout<<"Destroying Base";}
};
class Derive: public Base
{
public:
Derive(){ cout<<"Constructing Derive";}
~Derive(){ cout<<"Destroying Derive";}
};
void main()
{
Base *basePtr = new Derive();
delete basePtr;
}
Output:
Constructing Base
Constructing Derive
Destroying Derive
Destroying Base
33
Dynamic Binding
Static Binding:
By default, matching of function call with the correct function definition happens at compile
time. This is called static binding or early binding or compile-time binding. Static binding is
achieved using function overloading and operator overloading. Even though there are two or
more functions with same name, compiler uniquely identifies each function depending on the
parameters passed to those functions.
Dynamic Binding:
C++ provides facility to specify that the compiler should match function calls with the correct
definition at the run time; this is called dynamic binding or late binding or run-time binding.
Dynamic binding is achieved using virtual functions. Base class pointer points to derived class
object. And a function is declared virtual in base class, and then the matching function is
identified at run-time using virtual table entry.
Program: Dynamic Binding
using namespace std;
class A
{
public:
virtual void display()
{
cout<<"Base";
}
};
class B:public A
{
public:
void display()
{
cout<<"Derived";
}
};
int main()
{
B b;
A *a=&b;
a->display();
34
return 0;
}