3CS4 OOPS Unit 3
3CS4 OOPS Unit 3
SN CONTENTS Hours
1 Introduction to different programming paradigm, characteristics of OOP, 8
Class, Object, data member, member function, structures in C++,
different access Specifiers, defining member function inside and outside
class, array of objects.
2 Concept of reference, dynamic memory allocation using new and delete 8
operators, inline functions, function overloading, function with default
arguments, constructors and destructors, friend function and classes,
using this pointer.
3 Inheritance, types of inheritance, multiple inheritance, virtual base class, 9
function overriding, abstract class and pure virtual function
4 Constant data member and member function, static data member and 9
member function, polymorphism, operator overloading, dynamic binding
and virtual function
5 Exception handling, Template, Stream class, File handling. 6
Total 40
Inheritance in C++
Inheritance is the capability of one class to acquire properties and characteristics from
another class. The class whose properties are inherited by other class is called
the Parent or Base or Super class. And, the class which inherits properties of other
class is called Child or Derived or Sub class.
Inheritance makes the code reusable. When we inherit an existing class, all its methods
and fields become available in the new class, hence code is reused.
NOTE: All members of a class except Private, are inherited
1|P ag e
class Animal
{
public:
int legs = 4;
};
int main()
{
Dog d;
cout << d.legs;
cout << d.tail;
}
4 1
1) Public Inheritance
This is the most used inheritance mode. In this the protected member of super class
becomes protected members of sub class and public becomes public.
class Subclass : public Superclass
2) Private Inheritance
In private mode, the protected and public members of super class become private
members of derived class.
class Subclass : Superclass // By default its private inheritance
2|P ag e
3) Protected Inheritance
In protected mode, the public and protected members of Super class becomes protected
members of Sub class.
class subclass : protected Superclass
1. Single Inheritance
2. Multiple Inheritance
3. Hierarchical Inheritance
4. Multilevel Inheritance
};
};
3|P ag e
Multiple Inheritance in C++
In this type of inheritance a single derived class may inherit from two or more than two
base classes.
4|P ag e
Order of Constructor Call with Inheritance in C++
Base class constructors are always called in the derived class constructors. Whenever
you create derived class object, first the base class default constructor is executed and
then the derived class's constructor finishes execution.
Points to Remember
1. Whether derived class's default constructor is called or parameterised is called, base
int x;
public:
// default constructor
Base()
};
5|P ag e
class Derived : public Base
int y;
public:
// default constructor
Derived()
// parameterized constructor
Derived(int i)
};
int main()
Base b;
Derived d1;
Derived d2(10);
You will see in the above example that with both the object creation of the Derived class,
Base class's default constructor is called.
6|P ag e
Base class Parameterized Constructor in Derived class
Constructor
We can explicitly mention to call the Base class's parameterized constructor when
Derived class's parameterized constructor is called.
class Base
int x;
public:
// parameterized constructor
Base(int i)
x = i;
};
int y;
public:
// parameterized constructor
Derived(int j):Base(j)
y = j;
};
int main()
Derived d(10) ;
7|P ag e
Why is Base class Constructor called inside Derived class?
Constructors have a special job of initializing the object properly. A Derived class
constructor has access only to its own class members, but a Derived class object also
have inherited property of Base class, and only base class constructor can properly
initialize base class members. Hence all the constructors are called, else object wouldn't
be constructed properly.
In this case, first class B constructor will be executed, then class C constructor and then
class A constructor.
Upcasting in C++
Upcasting is using the Super class's reference or pointer to refer to a Sub class's object.
Or we can say that, the act of converting a Sub class's reference or pointer into its Super
class's reference or pointer is called Upcasting.
class Super
int x;
public:
void funBase()
};
8|P ag e
int y;
};
int main()
Sub obj;
ptr = &obj;
ref=obj;
Also, assignment operator = is never inherited. It can be overloaded but can't be inherited
by sub class.
3. Static Member functions can never be virtual. We will study about Virtual in coming topics.
9|P ag e
Hybrid Inheritance and Virtual Class in C++
In Multiple Inheritance, the derived class inherits from more than one base class. Hence,
in Multiple Inheritance there are a lot chances of ambiguity.
class A
{
void show();
};
class B:public A
{
void show();
// class definition
};
class C:public A
{
void show();
// class defintion
};
int main()
D obj;
obj.show();
In this case both class B and C inherits function show() from class A. Hence class D has
two inherited copies of function show(). In main() function when we call function show(),
then ambiguity arises, because compiler doesn't know which show() function to call.
Hence we use Virtual keyword while inheriting class.
class B : virtual public A
{
// class definition
};
before class D's constructor, constructors of its super classes will be called, hence
when constructors of class B and class C are called, they will again make a call to their
This will result in multiple calls to the constructor of class A, which is undesirable. As
there is a single instance of virtual base class which is shared by multiple classes that
inherit from it, hence the constructor of the base class is only called once by the
constructor of concrete class, which in our case is class D.
If there is any call for initializing the constructor of class A in class B or class C, while
creating object of class D, all such calls will be skipped.
class Base {
public:
void print() {
// code
}
};
11 | P a g e
public:
void print() {
// code
}
};
int main() {
Derived derived1;
Base* base1 = &derived1;
return 0;
}
In order to avoid this, we declare the print() function of the Base class as virtual
by using the virtual keyword.
class Base {
public:
virtual void print() {
// code
}
};
#include <iostream>
using namespace std;
class Base {
public:
virtual void print() {
cout << "Base Function" << endl;
}
};
int main() {
Derived derived1;
return 0;
}
Output
Derived Function
13 | P a g e
C++ override Identifier
C++ 11 has given us a new identifier override that is very useful to avoid bugs
while using virtual functions.
This identifier specifies the member functions of the derived classes that
override the member function of the base class.
For example,
class Base {
public:
int a;
virtual void print() {
// code
}
};
14 | P a g e
// code
}
};
If we use a function prototype in Derived class and define that function outside
of the class, then we use the following code:
Using the override identifier prompts the compiler to display error messages
when these mistakes are made.
Otherwise, the program will simply compile but the virtual function will not be
overridden.
Functions with incorrect names: For example, if the virtual function in the
base class is named print() , but we accidentally name the overriding function
in the derived class as pint() .
Functions with different return types: If the virtual function is, say,
of void type but the function in the derived class is of int type.
Functions with different parameters: If the parameters of the virtual function
and the functions in the derived classes don't match.
No virtual function is declared in the base class.
15 | P a g e
Use of C++ Virtual Functions
Suppose we have a base class Animal and derived classes Dog and Cat .
Suppose each class has a data member named type . Suppose these variables
are initialized through their respective constructors.
class Animal {
private:
string type;
... .. ...
public:
Animal(): type("Animal") {}
... .. ...
};
We could create both these functions in each class separately and override
them, which will be long and tedious.
Or we could make getType() virtual in the Animal class, then create a single,
separate print() function that accepts a pointer of Animal type as its argument.
We can then use this single function to override the virtual function.
16 | P a g e
class Animal {
... .. ...
public:
... .. ...
virtual string getType {...}
};
... .. ...
... .. ...
This will make the code shorter, cleaner, and less repetitive.
#include <iostream>
#include <string>
using namespace std;
class Animal {
private:
string type;
public:
// constructor to initialize type
Animal() : type("Animal") {}
public:
// constructor to initialize type
Dog() : type("Dog") {}
17 | P a g e
string getType() override {
return type;
}
};
public:
// constructor to initialize type
Cat() : type("Cat") {}
int main() {
Animal* animal1 = new Animal();
Animal* dog1 = new Dog();
Animal* cat1 = new Cat();
print(animal1);
print(dog1);
print(cat1);
return 0;
}
Output
Animal: Animal
Animal: Dog
Animal: Cat
Here, we have used the virtual function getType() and an Animal pointer ani in
order to avoid repeating the print() function in every class.
18 | P a g e
In main() , we have created 3 Animal pointers to dynamically create objects
of Animal , Dog and Cat classes.
2. When print(dog1) is called, the pointer points to a Dog object. So, the virtual
function is overridden and the function of Dog is executed inside of print() .
3. When print(cat1) is called, the pointer points to a Cat object. So, the virtual
function is overridden and the function of Cat is executed inside of print() .
public:
void show()
19 | P a g e
};
public:
void show()
int main()
b = &d;
Base class
When we use Base class's pointer to hold Derived class's object, base class pointer or
reference will always call the base version of the function
public:
};
20 | P a g e
class Derived:public Base
public:
void show()
int main()
b = &d;
Derived class
On using Virtual keyword with Base class's function, Late Binding takes place and the derived
version of function will be called, because base class pointer pointes to Derived class object.
class A
public:
21 | P a g e
cout << "Base class\n";
};
class B: public A
private:
};
int main()
A *a;
B b;
a = &b;
a->show();
Derived class
22 | P a g e
Mechanism of Late Binding in C++
To accomplich late binding, Compiler creates VTABLEs, for each class with virtual function.
The address of virtual functions is inserted into these tables. Whenever an object of such class is
created the compiler secretly inserts a pointer called vpointer, pointing to VTABLE for that
object. Hence when function is called, compiler is able to resovle the call by binding the correct
function using the vpointer.
3. The address of the virtual Function is placed in the VTABLE and the copiler uses VPTR(vpointer) to
23 | P a g e
Characteristics of Abstract Class
1. Abstract class cannot be instantiated, but pointers and references of Abstract class type
can be created.
2. Abstract class can have normal functions and variables along with a pure virtual function.
3. Abstract classes are mainly used for Upcasting, so that its derived classes can use its
interface.
4. Classes inheriting an Abstract Class must implement all pure virtual functions, or else
class Base
public:
};
public:
void show()
24 | P a g e
cout << "Implementation of Virtual Function in Derived class\n";
};
int main()
Base *b;
Derived d;
b = &d;
b->show();
In the above example Base class is abstract, with pure virtual show() function, hence we
cannot create object of base class.
want all the derived classes to have. Still you cannot create object of Abstract class.
Also, the Pure Virtual function must be defined outside the class definition. If you will
define it inside the class definition, complier will give an error. Inline pure virtual definition
is Illegal.
class Base
25 | P a g e
public:
};
public:
void show()
};
int main()
Base *b;
Derived d;
b = &d;
b->show();
26 | P a g e
Upcasting without Virtual Destructor in C++
Lets first see what happens when we do not have a virtual Base class destructor.
class Base
public:
~Base()
};
public:
~Derived()
};
int main()
delete b;
Base Destructor
In the above example, delete b will only call the Base class destructor, which is
undesirable because, then the object of Derived class remains undestructed, because its
destructor is never called. Which results in memory leak.
27 | P a g e
{
public:
virtual ~Base()
};
public:
~Derived()
};
int main()
delete b;
Derived Destructor
Base Destructor
When we have Virtual destructor inside the base class, then first Derived class's
destructor is called and then Base class's destructor is called, which is the desired
behaviour.
28 | P a g e
The only difference between Virtual and Pure Virtual Destructor is, that pure virtual
destructor will make its Base class Abstract, hence you cannot create object of that class.
class Base
public:
};
Base::~Base()
public:
~Derived()
};
29 | P a g e