You are on page 1of 34

1

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

UNIT II INHERITANCE & POLYMORPHISM

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.

Base Classes and Derived Classes


One of the most important concepts in object-oriented programming is that of inheritance.
Inheritance allows us to define a class in terms of another class, which makes it easier to create
and maintain an application. This also provides an opportunity to reuse the code functionality
and fast implementation time.
When creating a class, instead of writing completely new data members and member functions,
the programmer can designate that the new class should inherit the members of an existing class.
This existing class is called the base class, and the new class is referred to as the derived class.
The idea of inheritance implements the is a relationship. For example, mammal IS-A animal,
dog IS-A mammal hence dog IS-A animal as well and so on.
Base & Derived Classes:
A class can be derived from more than one classes, which means it can inherit data and functions
from multiple base classes. To define a derived class, we use a class derivation list to specify the
base class(es). A class derivation list names one or more base classes and has the form:
class derived-class: access-specifier base-class
Where access-specifier is one of public, protected, or private, and base-class is the name of a
previously defined class. If the access-specifier is not used, then it is private by default.

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();
}

Access Control and Inheritance:

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

A derived class cannot inherits

Constructors, destructors and copy constructors of the base class.

Overloaded operators of the base class.

The friend functions of the base class.

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;

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();
}
Multiple Inheritance

In this type of inheritance a single derived class may inherit from two or more than two base
classes.

Program: Multiple Inheritance


#include <iostream>
using namespace std;
// Base class Shape
class Shape
{
protected:
int width;
int height;
};
// Base class PaintCost
class PaintCost
{
public:
int getCost(int area)
{
return area * 70;
}
};
// Derived class
class Rectangle: public Shape, public PaintCost
{
public:
int getArea()
{
cin>>width>>height;
return (width * height);
}
};
int main( )
{
Rectangle Rect;
int area;
area = Rect.getArea();
// Print the area of the object.
cout << "Total area: " << Rect.getArea() << endl;
// Print the total cost of painting
cout << "Total paint cost: $" << Rect.getCost(area) << endl;
return 0;
}

Hierarchical Inheritance

In this type of inheritance, multiple derived classes inherits from a single base class.

Program: Hierarchy Inheritance


#include<iostream>
class person
{
private:
char name[20];
long int phno;
public:
void read()
{
cout<<"\n Enter name ";
cin>>name;
cout<<"\n Enter Phno.=";
cin>>phno;
}
void show()
{
cout<<"\n Name="<<name;
cout<<"\n Phone="<<phno;
}
};
class student : public person
{
private:
int rollno;
char course[20];
public:
void read()
{
cout<<"\n Enter Roll No.=";
cin>>rollno;

10

cout<<"\n Enter Course=";


cin>>course;
}
void show()
{
cout<<"\n Roll No.="<<rollno;
cout<<"\n Course="<<course;
}
};
class teacher : public person
{
private:
char dept_name[10];
char qual[10];
public:
void read()
{
person::read();
cout<<"\n Enter dept_name andQualification=";
cin>>dept_name>>qual;
}
void show()
{
person::show();
cout<<"\n Departement="<<dept_name;
cout<<"\n Qualififcation="<<qual;
}
};
main()
{
student s1;
cout<<"\n************************ Enter student Information******************";
s1.read();
cout<<"\n************************ Displaying Student Information*************";
s1.show();
teacher t1;
cout<<"\n************************** Enter Teacher Information*****************";
t1.read();
cout<<"\n*****************************Displaying Teacher Information************";
t1.show();
}

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.

Program: Multilevel Inheritance


#include<iostream.h>
#include<conio.h>
class Student
{
protected:
int roll;
public:
void get_num(int);
void put_num();
};
void Student::get_num(int a)
{
roll=a;
}
void Student::put_num()
{
cout<<"Roll number is "<<roll<<"\n";
}
class Test:public Student
{
protected:
float sub1,sub2;
public:
void get_mks(float,float);

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

Hybrid Inheritance is combination of hierarchical, multiple and multilevel Inheritance.

Program: Hybrid Inheritance


#include<iostream.h>
#include<conio.h>
int a,b,c,d,e;
class A
{
protected:
public:
void getab()
{
cout<<"\n ENter a and b value:";
cin>>a>>b;
}
};
class B:public A
{
protected:
public:
void getc()
{
cout<<"Enter c value:";
cin>>c;
}
};
class C
{

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();
}

Casting Class pointers and Member Functions


1. C++ lets you convert between datatypes. This is called casting. Sometimes this happens
automatically. For example,
int i=7;
float f=i;
now, integer i is converted in to float.
2. C++ has 4 casting operators - const_cast,static_cast, dynamic_cast, and reinterpret_cast.
Some of these will be mentioned later.

15

Casting between user-defined types


Implicit casting can happen between standard types (like float, double, etc). It can also happen
between related user-defined types. The following code compiles without protest. Here integer i
is converted in to float using the derived class object.
class base
{
public:
int i;
};
class derived: public base {
public:
float f;
};
int main () {
base b;
derived d;
b=d;
}

The casting operators


static_cast - Such conversions rely on static (compile-time) type information. More
generally, a static_cast may be used to perform the explicit inverse of the implicit
standard conversions.
reinterpret_cast - to perform type conversions on unrelated types.You should use this type
of cast only when absolutely necessary.
Pointers and casting
Pointers can be cast too. Use an explicit cast to convert a base-class pointer to a derivedclass pointer If pointer is going to be dereferenced, the type of the pointer must match the type
of object to which the pointer points
The syntax is derivedPtr = static_cast< DerivedClass * > basePtr;
class base
{
public:
int i;
};
class derived: public base {
public:

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

Accessing the Overridden Function in Base Class From Derived Class


To access the overridden function of base class from derived class, scope resolution operator ::.
For example: If you want to access get_data() function of base class from derived class in above
example then, the following statement is used in derived class.
A::get_data; // Calling get_data() of class A.
It is because, if the name of class is not specified, the compiler thinks get_data() function is
calling itself.

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;
}

Public, Protected and Private Inheritance


We can declare a derived class from a base class with different access control, i.e., public
inheritance, protected inheritance or private inheritance.
class base
{
.... ... ....
};
class derived : access_specifier base
{
.... ... ....
};
/* Note: Either keyword public, protected or private is used in place of access_specifier.

Private Inheritance
The Public and protected members of Base class become private members of the derived class.
class base
{
.... ... ....
};
class derived : private base
{
.... ... ....
};

20

Accessibility in Private Inheritance


Accessibility

private

protected

public

Accessible from own class?

yes

yes

yes

Accessible from dervied class?

no

yes

yes

no

no

no

Accessible outside dervied


class?

Public Inheritance
All the public members and protected members are inherited as public and protected
respectively.
class base
{
.... ... ....
};
class derived : public base
{
.... ... ....
};

Accessibility in Public Inheritance


Accessibility

private

protected

public

Accessible from own class?

yes

yes

yes

Accessible from dervied class?

no

yes

yes

no

no

yes

Accessible outside dervied


class?

Protected Inheritance
Public and Protected members are derived as protected members.

21

class base
{
.... ... ....
};
class derived : protected base
{
.... ... ....
};

Accessibility in Protected Inheritance


Accessibility

private

protected

public

Accessible from own class?

yes

yes

yes

Accessible from dervied class?

no

yes

yes

no

no

no

Accessible outside dervied


class?

Constructors and Destructors in derived Classes


1. During inheritance, base class may also contain constructor and destructor.
In this case if you create an instance for the derived class then base class constructor
will also be invoked and when derived instance is destroyed then base destructor will
also be invoked.
2. The order of execution is
I. Base constructor
II. Derived constructor
III. Derived destructor
IV. Base destructor
class Base
{
public:
Base ( )
{
cout << "Inside Base constructor" << endl;

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

Implicit Derived-Class Object to Base Class


1. Assignment of derived and base classes
Derived-class type and base-class type are different
Derived-class object can be treated as a base-class object

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

Abstract Base Classes and Concrete Classes


An interface describes the behavior or capabilities of a C++ class without committing to a
particular implementation of that class.
The C++ interfaces are implemented using abstract classes and these abstract classes should not
be confused with data abstraction which is a concept of keeping implementation details separate
from associated data.
A class is made abstract by declaring at least one of its functions as pure virtual function. A pure
virtual function is specified by placing "= 0" in its declaration as follows:
class Box
{
public:
// pure virtual function
virtual double getVolume() = 0;
private:

};

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;
}

You might also like