0% found this document useful (0 votes)
41 views29 pages

3CS4 OOPS Unit 3

This document provides an overview of object-oriented programming and inheritance in C++. It discusses key concepts like classes, objects, inheritance, polymorphism, and different types of inheritance like single, multiple, and multilevel inheritance. It also covers access specifiers, constructors, destructors, and static functions with inheritance.

Uploaded by

niworah679
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
41 views29 pages

3CS4 OOPS Unit 3

This document provides an overview of object-oriented programming and inheritance in C++. It discusses key concepts like classes, objects, inheritance, polymorphism, and different types of inheritance like single, multiple, and multilevel inheritance. It also covers access specifiers, constructors, destructors, and static functions with inheritance.

Uploaded by

niworah679
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 29

3CS4-06: Object Oriented Programming UNIT-III Notes

Max. Marks : 150 (IA:30,ETE:120)

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

Purpose of Inheritance in C++


1. Code Reusability
2. Method Overriding (Hence, Runtime Polymorphism.)

3. Use of Virtual Keyword

Basic Syntax of Inheritance


class Subclass_name : access_mode Superclass_name
While defining a subclass like this, the super class must be already defined or atleast
declared before the subclass declaration.
Access Mode is used to specify, the mode in which the properties of superclass will be
inherited into subclass, public, privtate or protected.
Example of Inheritance
Whenever we want to use something from an existing class in a new class, we can use
the concept on Inheritance. Here is a simple example,

1|P ag e
class Animal
{
public:

int legs = 4;
};

// Dog class inheriting Animal class


class Dog : public Animal
{
public:
int tail = 1;
};

int main()
{
Dog d;
cout << d.legs;
cout << d.tail;
}

4 1

Access Modifiers and Inheritance: Visibility of


Class Members
Depending on Access modifier used while inheritance, the availability of class members
of Super class in the sub class changes. It can either be private, protected or public.

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

Table showing all the Visibility Modes


Derived Class Derived Class Derived Class

Base class Public Mode Private Mode Protected Mode

Private Not Inherited Not Inherited Not Inherited

Protected Protected Private Protected

Public Public Private Protected

Types of Inheritance in C++


In C++, we have 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 C++


In this type of inheritance one derived class inherits from only one base class. It is the
most simplest form of Inheritance.
Class Base

};

Class Derived : public Base

};

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.

Hierarchical Inheritance in C++


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

Multilevel Inheritance in C++


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.

Hybrid (Virtual) Inheritance in C++


Hybrid Inheritance is combination of Hierarchical and Mutilevel Inheritance.

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.

Order of Constructor call


Base -> Derived Class Constructor

Points to Remember
1. Whether derived class's default constructor is called or parameterised is called, base

class's default constructor is always called inside them.

2. To call base class's parameterised constructor inside derived class's parameterised


constructor, we must mention it explicitly while declaring derived class's parameterized
constructor.

Base class Default Constructor in Derived class


Constructors
Default constructor is present in all the classes. In the below example we will see when
and why Base class's and Derived class's constructors are called.
class Base

int x;

public:

// default constructor

Base()

cout << "Base default constructor\n";

};

5|P ag e
class Derived : public Base

int y;

public:

// default constructor

Derived()

cout << "Derived default constructor\n";

// parameterized constructor

Derived(int i)

cout << "Derived parameterized constructor\n";

};

int main()

Base b;

Derived d1;

Derived d2(10);

Base default constructor

Base default constructor

Derived default constructor

Base default constructor

Derived parameterized constructor

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;

cout << "Base Parameterized Constructor\n";

};

class Derived : public Base

int y;

public:

// parameterized constructor

Derived(int j):Base(j)

y = j;

cout << "Derived Parameterized Constructor\n";

};

int main()

Derived d(10) ;

Base Parameterized Constructor

Derived Parameterized Constructor

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.

Constructor call in Multiple Inheritance in C++


Its almost the same, all the Base class's constructors are called inside derived class's
constructor, in the same order in which they are inherited.
class A : public B, public C ;

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

cout << "Super function";

};

class Sub:public Super

8|P ag e
int y;

};

int main()

Super* ptr; // Super class pointer

Sub obj;

ptr = &obj;

Super &ref; // Super class's reference

ref=obj;

The opposite of Upcasting is Downcasting, in which we convert Super class's reference


or pointer into derived class's reference or pointer. We will study more about
Downcasting later

Functions that are never Inherited


 Constructors and Destructors are never inherited and hence never overrided.(We will

study the concept of function overriding in the next tutorial)

 Also, assignment operator = is never inherited. It can be overloaded but can't be inherited

by sub class.

Inheritance and Static Functions in C++


1. They are inherited into the derived class.
2. If you redefine a static member function in derived class, all the other overloaded

functions in base class are hidden.

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

class D:public B, public C


{
void show();
void show();
// class definition
};

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

class C : virtual public A


{
// class definition
};
10 | P a g e
class D : public B, public C
{
// class definition
};
Now by adding virtual keyword, we tell compiler to call any one out of the
two show() funtions.

Hybrid Inheritance and Constructor call


As we all know that whenever a derived class object is instantiated, the base class
constructor is always called. But in case of Hybrid Inheritance, as discussed in above
example, if we create an instance of class D, then following constructors will be called :

 before class D's constructor, constructors of its super classes will be called, hence

constructors of class B, class C and class A will be called.

 when constructors of class B and class C are called, they will again make a call to their

super class's constructor.

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.

C++ Virtual Functions

A virtual function is a member function in the base class that we expect


to redefine in derived classes.

Basically, a virtual function is used in the base class in order to ensure


that the function is overridden. This especially applies to cases where a
pointer of base class points to an object of a derived class.
For example, consider the code below:

class Base {
public:
void print() {
// code
}
};

class Derived : public Base {

11 | P a g e
public:
void print() {
// code
}
};

Later, if we create a pointer of Base type to point to an object of Derived class


and call the print() function, it calls the print() function of the Base class.
In other words, the member function of Base is not overridden.

int main() {
Derived derived1;
Base* base1 = &derived1;

// calls function of Base class


base1->print();

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

Example 1: C++ virtual Function

#include <iostream>
using namespace std;

class Base {
public:
virtual void print() {
cout << "Base Function" << endl;
}
};

class Derived : public Base {


12 | P a g e
public:
void print() {
cout << "Derived Function" << endl;
}
};

int main() {
Derived derived1;

// pointer of Base type that points to derived1


Base* base1 = &derived1;

// calls member function of Derived class


base1->print();

return 0;
}

Output

Derived Function

Here, we have declared the print() function of Base as virtual.


So, this function is overridden even when we use a pointer of Base type that
points to the Derived object derived1.

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

class Derived : public Base {


public:
void print() override {

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:

class Derived : public Base {


public:
int a; // function prototype
void print() override;
};
// function definition
void Derived::print() {
// code
}

Use of C++ override

When using virtual functions. it is possible to make mistakes while declaring


the member functions of the derived classes.

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.

Some of these possible mistakes are:

 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") {}
... .. ...
};

class Dog : public Animal {


private:
string type;
... .. ...
public:
Animal(): type("Dog") {}
... .. ...
};

class Cat : public Animal {


private:
string type;
... .. ...
public:
Animal(): type("Cat") {}
... .. ...
};

Now, let us suppose that our program requires us to create


two public functions for each class:
1. getType() to return the value of type

2. print() to print the value of type

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

... .. ...
... .. ...

void print(Animal* ani) {


cout << "Animal: " << ani->getType() << endl;
}

This will make the code shorter, cleaner, and less repetitive.

Example 2: C++ virtual Function Demonstration

// C++ program to demonstrate the use of virtual function

#include <iostream>
#include <string>
using namespace std;

class Animal {
private:
string type;

public:
// constructor to initialize type
Animal() : type("Animal") {}

// declare virtual function


virtual string getType() {
return type;
}
};

class Dog : public Animal {


private:
string type;

public:
// constructor to initialize type
Dog() : type("Dog") {}

17 | P a g e
string getType() override {
return type;
}
};

class Cat : public Animal {


private:
string type;

public:
// constructor to initialize type
Cat() : type("Cat") {}

string getType() override {


return type;
}
};

void print(Animal* ani) {


cout << "Animal: " << ani->getType() << endl;
}

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.

void print(Animal* ani) {


cout << "Animal: " << ani->getType() << endl;
}

18 | P a g e
In main() , we have created 3 Animal pointers to dynamically create objects
of Animal , Dog and Cat classes.

// dynamically create objects using Animal pointers


Animal* animal1 = new Animal();
Animal* dog1 = new Dog();
Animal* cat1 = new Cat();

We then call the print() function using these pointers:


1. When print(animal1) is called, the pointer points to an Animal object. So, the
virtual function in Animal class is executed inside of print() .

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() .

Virtual Functions in C++


Virtual Function is a function in base class, which is overrided in the derived class, and
which tells the compiler to perform Late Binding on this function.
Virtual Keyword is used to make a member function of the base class Virtual.

Late Binding in C++


In Late Binding function call is resolved at runtime. Hence, now compiler determines the
type of object at runtime, and then binds the function call. Late Binding is also
called Dynamic Binding or Runtime Binding.

Problem without Virtual Keyword


Let's try to understand what is the issue that virtual keyword fixes,
class Base

public:

void show()

cout << "Base class";

19 | P a g e
};

class Derived:public Base

public:

void show()

cout << "Derived Class";

int main()

Base* b; //Base class pointer

Derived d; //Derived class object

b = &d;

b->show(); //Early Binding Ocuurs

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

Using Virtual Keyword in C++


We can make base class's methods virtual by using virtual keyword while declaring them. Virtual
keyword will lead to Late Binding of that method.
class Base

public:

virtual void show()

cout << "Base class\n";

};

20 | P a g e
class Derived:public Base

public:

void show()

cout << "Derived Class";

int main()

Base* b; //Base class pointer

Derived d; //Derived class object

b = &d;

b->show(); //Late Binding Ocuurs

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.

Using Virtual Keyword and Accessing Private Method of


Derived class
We can call private function of derived class from the base class pointer with the help of virtual
keyword. Compiler checks for access specifier only at compile time. So at run time when late
binding occurs it does not check whether we are calling the private function or public function.
#include <iostream>

using namespace std;

class A

public:

virtual void show()

21 | P a g e
cout << "Base class\n";

};

class B: public A

private:

virtual void show()

cout << "Derived class\n";

};

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.

Important Points to Remember


1. Only the Base class Method's declaration needs the Virtual Keyword, not the definition.
2. If a function is declared as virtual in the base class, it will be virtual in all its derived classes.

3. The address of the virtual Function is placed in the VTABLE and the copiler uses VPTR(vpointer) to

point to the Virtual Function.

Abstract Class and Pure Virtual Function in C++


Abstract Class is a class which contains at least one Pure Virtual function in it. Abstract
classes are used to provide an Interface for its sub classes. Classes inheriting an
Abstract Class must provide definition to the pure virtual function, otherwise they will also
become abstract class.

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

they will become Abstract too.

Pure Virtual Functions in C++


Pure virtual Functions are virtual functions with no definition. They start
with virtual keyword and ends with = 0. Here is the syntax for a pure virtual function,

virtual void f() = 0;

Example of Abstract Class in C++


Below we have a simple example where we have defined an abstract class,
//Abstract base class

class Base

public:

virtual void show() = 0; // Pure Virtual Function

};

class Derived:public Base

public:

void show()

24 | P a g e
cout << "Implementation of Virtual Function in Derived class\n";

};

int main()

Base obj; //Compile Time Error

Base *b;

Derived d;

b = &d;

b->show();

Implementation of Virtual Function in Derived class

In the above example Base class is abstract, with pure virtual show() function, hence we
cannot create object of base class.

Why can't we create Object of an Abstract Class?


When we create a pure virtual function in Abstract class, we reserve a slot for a function
in the VTABLE(studied in last topic), but doesn't put any address in that slot. Hence the
VTABLE will be incomplete.
As the VTABLE for Abstract class is incomplete, hence the compiler will not let the
creation of object for such class and will display an errror message whenever you try to
do so.

Pure Virtual definitions


 Pure Virtual functions can be given a small definition in the Abstract class, which you

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.

// Abstract base class

class Base

25 | P a g e
public:

virtual void show() = 0; //Pure Virtual Function

};

void Base :: show() //Pure Virtual definition

cout << "Pure Virtual definition\n";

class Derived:public Base

public:

void show()

cout << "Implementation of Virtual Function in Derived class\n";

};

int main()

Base *b;

Derived d;

b = &d;

b->show();

Implementation of Virtual Function in Derived class

Virtual Destructors in C++


Destructors in the Base class can be Virtual. Whenever Upcasting is done, Destructors of
the Base class must be made virtual for proper destrucstion of the object when the
program exits.
NOTE: Constructors are never Virtual, only Destructors can be Virtual.

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

cout << "Base Destructor\n";

};

class Derived:public Base

public:

~Derived()

cout<< "Derived Destructor\n";

};

int main()

Base* b = new Derived; // Upcasting

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.

Upcasting with Virtual Destructor in C++


Now lets see. what happens when we have Virtual destructor in the base class.
class Base

27 | P a g e
{

public:

virtual ~Base()

cout << "Base Destructor\n";

};

class Derived:public Base

public:

~Derived()

cout<< "Derived Destructor";

};

int main()

Base* b = new Derived; // Upcasting

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.

Pure Virtual Destructors in C++


 Pure Virtual Destructors are legal in C++. Also, pure virtual Destructors must be defined,

which is against the pure virtual 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.

 There is no requirement of implementing pure virtual destructors in the derived classes.

class Base

public:

virtual ~Base() = 0; // Pure Virtual Destructor

};

// Definition of Pure Virtual Destructor

Base::~Base()

cout << "Base Destructor\n";

class Derived:public Base

public:

~Derived()

cout<< "Derived Destructor";

};

29 | P a g e

You might also like