Unit-III
POLYMORPHISM
Definition
The word polymorphism means having
many forms.
The ability of a message to be displayed in
more than one form
E.g,
Person at the same time can have different
characteristics.
Same person posses different behaviour in
different situations.
This is called polymorphism.
Types of Polymorphism
Polymorphism
Compile Time
Polymorphism Run time Polymorphism
Function Operator Function Virtual
Overloading Overloading Overriding Function
Compile Time
Polymorphism
This is also known as static (or early) binding.
Function overloading and Operator overloading
are perfect example of Compile time
polymorphism.
Function Overloading:-
When there are multiple functions with same
name but different parameters then these
functions are said to be overloaded. Functions
can be overloaded by change in number of
arguments or/and change in type of
arguments.
//Program:Function overlodding
#include <iostream>
using namespace std;
class Cal {
public:
static int add(int a,int b){
return a + b;
}
static int add(int a, int b, int c)
{
return a + b + c;
}
};
int main(void) {
Cal C; // class object declaration.
cout<<C.add(10, 20)<<endl;
cout<<C.add(12, 20, 23);
return 0;
}
30 55
Output
30
55
//Program:Function overlodding
#include<iostream>
using namespace std;
int mul(int,int);
float mul(float,int);
int mul(int a,int b)
{
return a*b;
}
float mul(double x, int y)
{
return x*y;
}
int main()
{
int r1 = mul(6,7);
float r2 = mul(0.2,3);
std::cout << "r1 is : " <<r1<< std::endl;
std::cout <<"r2 is : " <<r2<< std::endl;
return 0;
}
30 55
Output
r1 is : 42
r2 is : 0.6
Operator Overloading:
An operator is a symbol that tells the compiler to
perform specific mathematical, logical calculations or
some other special operations.
C++ also provide option to overload operators.
For example, we can make the operator (‘+’) for string
class to concatenate two strings. We know that this is
the addition operator whose task is to add two operands.
So a single operator ‘+’ when placed between integer
operands , adds them and when placed between string
operands, concatenates them.
Operator Overloading
Operator overloading is a compile-time polymorphism
in which the operator is overloaded to provide the
special meaning to the user-defined data type.
Operator overloading is used to overload or redefines
most of the operators available in C++.
It is used to perform the operation on the user-
defined data type.
For example, C++ provides the ability to add the
variables of the user-defined data type that is applied
to the built-in data types.
The advantage of Operators overloading is to perform
different operations on the same operand
Operator that cannot be overloaded are as
follows:
Scope operator (::)
Sizeof
member selector(.)
member pointer selector(*)
ternary operator(?:)
Operator Overloading
In C++, we can change the way operators work for
user-defined types like objects and structures. This
is known as operator overloading. For example,
Suppose we have created three objects c1, c2 and
result from a class named Complex that represents
complex numbers.
Since operator overloading allows us to change
how operators work, we can redefine how the +
operator works and use it to add the complex
numbers of c1 and c2 by writing the following code:
Run-Time polymorphism
It is also called as dynamic binding.
Function overriding is an example of
Runtime polymorphism.
Function Overriding: When child class
declares a method, which is already present
in the parent class then this is called
function overriding, here child class
overrides the parent class.
Function Overriding
Function overriding in C++ is a feature that
allows us to use a function in the child class
that is already present in its parent class.
The child class inherits all the data
members, and the member functions
present in the parent class.
If you wish to override any functionality in
the child class, then you can implement
function overriding. Function overriding
means creating a newer version of the
parent class function in the child class.
// C++ program to demonstrate function
overriding
#include <iostream>
using namespace std;
class Base {
public:
void print() {
cout << "Base Function" << endl;
}
};
class Derived : public Base {
public:
void print() {
cout << "Derived Function" << endl;
}
};
int main() {
Derived derived1;
derived1.print();
return 0;
Output
Derived Function
// C++ program to access overridden function
// in main() using the scope resolution operator ::
#include <iostream>
using namespace std;
class Base {
public:
void print() {
cout << "Base Function" << endl;
}
};
class Derived : public Base {
public:
void print() {
cout << "Derived Function" << endl;
}
};
int main() {
Derived derived1, derived2;
derived1.print();
// access print() function of the Base class
derived2.Base::print();
return 0;
Output:
Derived Function
Base Function
Virtual Function
A virtual function is a member function which is declared
within a base class and is re-defined (overridden) by a
derived class. When you refer to a derived class object
using a pointer or a reference to the base class, you can
call a virtual function for that object and execute the
derived class’s version of the function.
Virtual functions ensure that the correct function is called
for an object, regardless of the type of reference (or
pointer) used for function call.
They are mainly used to achieve Runtime polymorphism
Functions are declared with a virtual keyword in base
class.
The resolving of function call is done at runtime.
Virtual Function
Rules for Virtual Functions
Virtual functions cannot be static.
A virtual function can be a friend function of another class.
Virtual functions should be accessed using pointer or reference
of base class type to achieve runtime polymorphism.
The prototype of virtual functions should be the same in the
base as well as derived class.
They are always defined in the base class and overridden in a
derived class. It is not mandatory for the derived class to
override (or re-define the virtual function), in that case, the
base class version of the function is used.
A class may have virtual destructor but it cannot have a
virtual constructor.
// CPP program to illustrate
// concept of Virtual Functions void show()
{
#include<iostream> cout << "show derived class\
using namespace std; n";
}
class base { };
public:
virtual void print() int main()
{ {
cout << "print base class\n";
base *bptr;
}
derived d;
bptr = &d;
void show()
{
cout << "show base class\n";
// Virtual function, binded at
} runtime
}; bptr->print();
class derived : public base { // Non-virtual function, binded at
public: compile time
void print() bptr->show();
{
cout << "print derived class\n"; return 0;
} }
Output:
print derived class
show base class
Explanation: Runtime polymorphism is achieved only
through a pointer (or reference) of base class type. Also,
a base class pointer can point to the objects of base
class as well as to the objects of derived class. In above
code, base class pointer ‘bptr’ contains the address of
object ‘d’ of derived class.
Late binding (Runtime) is done in accordance with the
content of pointer (i.e. location pointed to by pointer)
and Early binding (Compile time) is done according to
the type of pointer, since print() function is declared
with virtual keyword so it will be bound at runtime
(output is print derived class as pointer is pointing to
object of derived class) and show() is non-virtual so it
will be bound during compile time (output is show base
class as pointer is of base type).
Why Operator Overloading
int i, j, k; // integers
float m, n, p; // floats The compiler overloads
the + operator for built-in
integer and float types by
k = i + j; default, producing integer
// integer addition and assignment addition with i+j, and
p = m + n; floating addition with m+n.
// floating addition and assignment
We can make object operation look like individual
int variable operation, using operator functions
Complex a,b,c;
c = a + b;
23
Rules of Operator
Overloading
Existing operators can only be overloaded, but the new
operators cannot be overloaded.
The overloaded operator contains atleast one operand of
the user-defined data type.
We cannot use friend function to overload certain
operators. However, the member function can be used to
overload those operators.
When unary operators are overloaded through a member
function take no explicit arguments, but, if they are
overloaded by a friend function, takes one argument.
When binary operators are overloaded through a member
function takes one explicit argument, and if they are
overloaded through a friend function takes two explicit
arguments.
Operators that can be overloaded
+ - * / % ^ & |
~ ! = < > += -= *=
/= %= ^= &= |= << >> >>=
<<= == != <= >= && || ++
-- ->* , -> [] () new delete
new[] delete[]
the operators that can not be overloaded by
friend function are as follows.
Assignment operator =
function call operator ()
subscriping operator []
class member access operator ->
The process of overloading involves the
following steps :
1) Create a class that defines the data type
that is to be used in the overloading
operation.
2) Declare the operator function operator
op() in the public part of the class. It may
be either a member function or a friend
function.
3) Define the operator function to implement
the required operations.
Operator functions must be either member
functions (non-static) or friend functions.
Basic difference between them is that a friend
function will have only one argument for unary
operators and two for binary operators, while a
member function has no arguments for unary
operators and only one for binary operators.
because the object used to invoke the member
function is passed implicitly and therefore is
available for the member function. This is not the
case with friend functions.
Operator Overloading
Syntax
Declaration Syntax of operator function :
Examples:
operator+
Return_type operator op(argument-list);
operator-
operator*
--- operator is a function operator/
--- op is one of C++ operator symbols (+, -, =, etc..)
29
Syntax
Definition Syntax of operator function :
return_type class_name :: operator op(argument-list)
{
Function body //task defined
In the above syntax Return_Type is value type to be returned
to another object, operator op is the function where the
operator is a keyword and op is the operator to be overloaded.
Operator function must be either non-static (member function)
or friend function.
30
Operator Overloading can be done by
using three approaches, they are:
Overloading unary operator.
Overloading binary operator.
Overloading binary operator using a friend
function.
Overloading unary
operator
Unary operator: are operators that act upon
a single operand to produce a new value.
Types of unary operators:
unary minus(-)
increment(++) ++a a++
decrement(- -)
NOT(!)
Addressof operator(&)
sizeof()
Overloading unary
operator
Overloading Unary Operator: Let us
consider to overload (-) unary operator. In
unary operator function, no arguments
should be passed. It works only with one
class objects. It is a overloading of an
operator operating on a single operand.
Overloading Binary
operator
A binary operator is an operator that
operates on two operands and manipulates
them to return a result.
You use binary operators very frequently
like addition (+) operator, subtraction (-)
operator and division (/) operator.
Example of overloading binary operator.
// C++ program to show void output()
unary operator {
overloading: cout<<"\nValue of
a="<<a;
#include<iostream>
}
using namespace std; };
class demo int main()
{ {
int a; demo aa;
public: aa.input();
void input() cout<<"\nValue before
increment:";
{
aa.output();
cout<<"Enter a No:"; ++aa;
cin>>a; cout<<"\nValue after
} increment:";
void operator++() aa.output();
{a=a+1; return 0;
Output:
Enter a No:8
Value before increment:
Value of a=8
Value after increment:
Value of a=9
// C++ program to show void output()
unary operator {
overloading: cout<<"\nValue of
a="<<a;
#include<iostream>
}
using namespace std; };
class demo int main()
{ {
int a; demo aa;
public: aa.input();
void input() cout<<"\nValue before
increment:";
{
aa.output();
cout<<"Enter a No:"; aa++;
cin>>a; cout<<"\nValue after
} increment:";
void operator++(int) aa.output();
{a=a+1; return 0;
Output:
Enter a No:8
Value before increment:
Value of a=8
Value after increment:
Value of a=9
// C++ program to show demo operator+(demo
binary operator bb)
overloading: { demo cc;
#include<iostream> cc.a=a+bb.a;
using namespace std; return cc;
class demo { }
int a; };
int main()
public:
{
void getdata() demo aa,bb,cc;
{ aa.getdata();
cout<<"Enter a No:"; bb.getdata();
cin>>a; cc=aa+bb;
} aa.putdata();
void putdata() bb.putdata();
cc.putdata();
{
return 0;
cout<<"\n Value="<<a; }
Output:
Enter a No:5
Enter a No:6
Value=5
Value=6
Value=11
// C++ program to show void operator=(demo
operator overloading: bb)
#include<iostream> {
using namespace std; a=bb.a;
class demo { }
int a; };
int main()
public:
{
void getdata() demo aa,bb;
{ bb.getdata();
cout<<"Enter a No:"; aa=bb;
cin>>a; aa.putdata();
} bb.putdata();
void putdata() return 0;
}
{
cout<<"\nValue="<<a;
}
Output:
Enter a No:9
Value=9
Value=9
// C++ program to show void operator+=(demo
operator overloading: bb)
#include<iostream> {
using namespace std; a=a+bb.a;
class demo { }
int a; };
int main()
public:
{
void getdata() demo aa,bb;
{ aa.getdata();
cout<<"Enter a No:"; bb.getdata();
cin>>a; aa.putdata();
} bb.putdata();
void putdata() aa+=bb;
aa.putdata();
{
return 0;
cout<<"\na="<<a; }
}
Output:
Enter a No:6
Enter a No:7
a=6
a=7
a=13
// C++ program to show complex operator+
operator overloading: (complex bb)
#include<iostream> {
using namespace std; complex cc;
cc.r=r+bb.r;
class complex {
cc.i=i+bb.i;
int r,i; return cc;
public: }
void getdata() };
{ int main()
cout<<"\nEnter Real and {
Imaginary:"; complex aa,bb,cc;
cin>>r>>i; aa.getdata();
bb.getdata();
}
cc=aa+bb;
void putdata() aa.putdata();
{ bb.putdata();
cout<<"\nReal="<<r<<"\ cc.putdata();
tImaginary="<<i; return 0;
} }
Output:
Enter Real and Imaginary:1 2
Enter Real and Imaginary:1 2
Real=1 Imaginary=2
Real=1 Imaginary=2
Real=2 Imaginary=4
Data Conversion
Data conversion in C++ includes
conversions between basic types and user-
defined types, and conversions between
different user-defined types.
The assignments between types, whether
they are basic types or user-defined types,
are handled by the compiler , provided that
the same data type is used on both sides of
the equal sign.
Types of Data Conversion
a. Conversion from basic to user defined
data type
b. Conversion from user-defined data
type to basic data type
c. Conversion between user defined data
types
Conversion from basic to user
defined data type
Conversion from basic to user defined type is done by using
the constructor function with one argument of basic type as
follows.
Example
Conversion constructor
class classname
{ private:
public:
classname(basic data type)
{
//Conversion code
}
};
// C++ program type- void Display()
conversion {
cout << "Time = " <<
#include <iostream> hour
using namespace std; << " hrs and "
<< mins << " mins\
class Time {
n";
int hour; }
int mins; };
public:
Time() int main()
{ {
Time T1;
hour = 0;
int dur = 95;
mins = 0;
} T1 = dur;
Time(int t) T1.Display();
{
hour = t / 60; return 0;
}
mins = t % 60;
Output:
} Time = 1 hrs and 35 mins
Conversion from user-defined
data type to basic data type
Conversion from user-defined type of basic
data type is done by overloading the cast
operator of basic type as a member
function.
Operator function is defined as an
overloaded basic data type which takes no
arguments.
Return type of operator is not specified
because the cast operator function itself
specifies the return type.
Conversion from user-defined
data type to basic data type
Syntax:
Operator Basicdatatype()
{
return
}
Now, this function converts a user-defined data type to a
primitive data type. For Example, the operator double()
converts a class object to type double, the operator int()
converts a class type object to type int, and so on. Below
is the program to illustrate the same:
#include <iostream>
using namespace std; int main()
class sample {
int h,m,duration;
{
h=2;
int hrs, mins; m=30;
public: sample s(h,m);
sample(int x, int y) duration=s;
{ cout<<duration;
hrs=x; return 0;
mins=y; }
} operator int()
Output:
{
150
return(hrs*60+mins);
}
Conversion between user defined data
types: Conversion in destination object
We have just seen data conversion techniques from a
basic to class type and a class to basic type. But
sometimes we would like to convert one class data type to
another class type.
Example
Obj1 = Obj2; //Obj1 and Obj2 are objects of different
classes.
Obj1 is an object of class one and Obj2 is an object of
class two. The class two type data is converted to class
one type data and the converted value is assigned to the
Obj1. Since the conversion takes place from class two to
class one, two is known as the source and one is known as
the destination class.
Such conversion between objects of different classes can
be carried out by either a constructor or a conversion
function.
Conversion between user defined data
types: Conversion in destination object
We have just seen data conversion techniques from a
basic to class type and a class to basic type. But
sometimes we would like to convert one class data
type to another class type.
This conversion is exactly like conversion of basic to
user defined data type i.e. one argument constructor
is used.
Conversion routine is defined as a one argument
constructor in destination class and takes the
argument of the source class type
Conversion in destination
object
E.g.
classA objA;
classB objB;
objA=objB;
Here, objB is the source of the
class classB and objA is the destination
object of class classA.
the conversion routine should exist
in classA (destination class type) as a one
argument constructor.
Conversion in destination
object
when a class needs to be converted, a casting
operator function can be used. The conversion
takes place in the source class and the result is
given to the destination class object.
Destination
Conversion Source class
class
Basic to class Not applicable Constructor
Class to Basic Casting operator Not applicable
Class to class Casting operator Constructor
Conversion between user defined data
types: Conversion in source object
This conversion is exactly like conversion of user-
defined type to basic type i.e. overloading the
cast operator is used.
E.g.
classA objA;
classB objB;
objA=objB;
objB is the source of the class classB and objA is
the destination object of class classA. Conversion
routine is specified as conversion (cast)
operator overloading for the type of
destination class.
Conversion in source object
//destination object class
class classA
{
//body of classA
} //source object class
class classB { private: //…. public:
operator classA () //cast operator destination
types { //code for conversion from
classB //to classA } };
#include <iostream>
{
using namespace std; cout<<"values="<<no1<<","<
class demo1 <no2<<endl;
{ }
public: void operator=(demo1 x)
{
int a,b;
cout<<"operator works\n";
demo1(int x,int y) no1=x.a;
{ no2=x.b;
a=x; }
b=y; };
} int main()
{
void output()
int x=10,y=7;
{ demo1 d1(x,y);
cout<<"values="<<a<<","<<b<<en demo2 d2;
dl; d2=d1;
} cout<<"d1 object:";
}; d1.output();
cout <<"d2 object:";
class demo2
d2.output();
{ return 0;
public: }
int no1,no2;
Output:
operator works
d1 object:values=10,7
d2 object:values=10,7
Type Casting
Converting an expression of a given type
into another type is known as type-casting.
There are two types of casting as
1. Implicit Casting
2. Explicit Casting
Implicit Casting
Implicit conversions do not require any operator.
They are automatically performed when a value is
copied to a compatible type.
It is done by compiler and there is no loss of
information
For example:
float a=20.10;
int b;
b=a;
The value is converted from float to int and we have
not had to specify any type-casting operator.
Implicit Casting
This is known as a standard conversion.
Standard conversions affect fundamental data
types, and allow conversions such as the
conversions between numerical types
(short to int, int to float, double to int...), to or
from bool, and some pointer conversions.
Some of these conversions may imply a loss of
precision, which the compiler can signal with a
warning.
This warning can be avoided with an explicit
conversion.
Implicit Casting
Implicit conversions also include constructor or operator
conversions, which affect classes that include specific
constructors or operator functions to perform conversions.
For example:
class A {};
class B {
public: B (A a) {}
};
A a;
B b=a;
Here, an implicit conversion happened between objects of class
A and class B, because B has a constructor that takes an
object of class A as parameter.
Therefore implicit conversions from A to B are allowed.
Example 1: Conversion From int to double
// Working of implicit type-conversion
#include <iostream>
using namespace std;
int main() {
int a=9;
double b;
b=a;
cout<<"a= "<<a<< endl;
cout<<“b= "<<b<< endl;
return 0;
Output
a= 9
b= 9
Example 2: Automatic Conversion from double to int
//Working of Implicit type-conversion
#include <iostream>
using namespace std;
int main() {
int a;
double b=9.99;
a=b;
cout<<"a= "<<a<< endl;
cout<<“b= "<<b<< endl;
return 0;
}
Output
a=9
#include<iostream>
using namespace std;
class Demo
{
private:
int data;
public:
Demo(int i):data(i)
{
}
void Display()
{
cout<<" data = "<<data<<endl;
}
};
int main()
{
Demo obj(6);
obj.Display();
obj = 27; // implicit conversion occurs here.
obj.Display();
return 0;
Output
data = 6
data = 27
Explicit Casting
For explicit conversion cast operator is used.
A cast is a special operator that forces one data type to be
converted into another.
As an operator, a cast is unary and has the same
precedence as any other unary operator.
The most general cast supported by most of the C++
compilers is as follows −
Where type is the desired data type.
(type) expression
e.g.
float a=20.20;
int b;
b =(int) a;
example
Case1: int a=10, b=3;
float c=a/b; output:3.0
Case2: int a=10, b=3;
float c=(float)a/b; output:3.33
Case3: int a=10, b=3;
float c=(float)(a/b); output:3.0
#include <iostream>
using namespace std;
int main() {
double pi= 3.56;
cout << “pi= " << pi<< endl;
int num1 = (int)pi;
cout << "num1= " << num1 << endl;
int num2 = int(pi);
cout << "num2= " << num2 << endl;
return 0;
}
Output:
pi= 3.56
num1= 3
Pitfalls of operator overloading and conversion
Precedence and Associativity of an operator
cannot be changed.
Arity (numbers of Operands) cannot be changed.
Unary operator remains unary, binary remains
binary etc.
No new operators can be created, only existing
operators can be overloaded.
Cannot redefine the meaning of a procedure. You
cannot change how integers are added.
Pre-increment /decrement and post
increment/decrement operator give same output
in operator overloading.
Pitfalls of operator overloading and conversion
Avoid ambiguity when use the operator
overloading and conversion.
Avoid the same conversion in more than one
way.
If number of overloaded operators are too large
and if the operators are used in non intuitive
ways, it became more complex than easier.
Not all operator can be overloaded.
Type conversion may increase the confusion.
Keywords mutable
Mutable data members are those members
whose values can be changed in runtime
even if the object is of constant type. It is
just opposite to constant.
Sometimes logic required to use only one or
two data member as a variable and another
one as a constant to handle the data. In
that situation, mutability is very helpful
concept to manage classes.
Keywords mutable
Sometimes there is requirement to modify
one or more data members of class through
const function even though you don’t want
the function to update other members of
class.
This task can be easily performed by using
mutable keyword.
Example
#include <iostream>
using namespace std;
class Test {
public:
int x;
mutable int y;
Test() { x = 4; y = 10; }
};
int main()
{
Test t1;
t1.y = 20;
cout << t1.y;
return 0;
}
Output:
20
#include <iostream>
using namespace std;
class Test {
public:
int x;
mutable int y;
Test() { x = 4; y = 10; }
};
int main()
{
const Test t1;
t1.x = 8;
cout << t1.x;
return 0;
}
Output:
prog.cpp: In function ‘int main()’:
prog.cpp:13:10: error: assignment of member
‘Test::x’ in read-only object
13 | t1.x = 8;
| ~~~~~^~~
Keyword explicit
Explicit Keyword in C++ is used to mark
constructors to not implicitly convert types in
C++. It is optional for constructors that take
exactly one argument and work on
constructors(with a single argument) since
those are the only constructors that can be
used in typecasting.
Let’s understand explicit keyword through an
example.
Predict the output of the following C++ Program
// explicit keyword
#include <iostream>
using namespace std;
class demo
{
int num;
public:
demo()
{
}
explicit demo(int x)
{
num=x;
}
void output()
{
cout<<"value="<<num<<endl;
}
};
int main()
{
demo d(10);
d.output();
return 0;
Pointers to base class
Pointer is a data type that stores the
address of other data types.
The pointer of Base Class pointing different
object of derived class:
Approach:
A derived class is a class which takes some properties
from its base class.
It is true that a pointer of one class can point to other
class, but classes must be a base and derived class,
then it is possible.
To access the variable of the base class, base class
pointer will be used.
So, a pointer is type of base class, and it can access
all, public function and variables of base class since
pointer is of base class, this is known as binding
pointer.
In this pointer base class is owned by base class but
points to derived class object.
Same works with derived class pointer, value is
changed.
// C++ program:
#include <iostream>
int main()
using namespace std;
class base {
{ base b;
public: derived d;
void show_val()
b.show_val();
{
cout<<"class::base"<<endl; d.show_val();
} }
};
class derived:public base Output:
{
class::base
public: class::derived
void show_val()
{
cout<<"class::derived"<<endl;
}
};
#include <iostream>
using namespace std;
class base
{
int main()
public: {
void show_val() base* b;
{ derived d;
cout<<"class::base"<<endl; b=&d;
} b->show_val();
return 0;
};
}
class derived:public base
{ Output:
public: class::base
void show_val()
{
cout<<"class::derived"<<endl;
}
};
Virtual Function
A virtual function is a member function
which is declared within a base class and is
re-defined(Overridden) by a derived class.
When you refer to a derived class object
using a pointer or a reference to the base
class, you can call a virtual function for that
object and execute the derived class’s
version of the function.
Virtual Function
Virtual functions ensure that the correct function
is called for an object, regardless of the type of
reference (or pointer) used for function call.
They are mainly used to achieve Runtime
polymorphism
Functions are declared with a virtual keyword in
base class.
The resolving of function call is done at Run-time.
Example
#include <iostream>
using namespace std;
class base
{
public: int main()
{
virtual void show_val()
base* b;
{ derived d;
cout<<"class::base"<<endl; b=&d;
} b->show_val();
}; return 0;
class derived:public base }
{
public:
Output:
class::derived
void show_val()
{
cout<<"class::derived"<<endl;
}
};
Rules Of Virtual Function
Virtual functions cannot be static and also cannot be a
friend function of another class.
Virtual functions should be accessed using pointer or
reference of base class type to achieve run time
polymorphism.
The prototype of virtual functions should be same in base
as well as derived class.
They are always defined in base class and overridden in
derived class. It is not mandatory for derived class to
override (or re-define the virtual function), in that case
base class version of function is used.
A class may have virtual destructor but it cannot have a
virtual constructor.
Virtual Function
NOTE:
If we have created a virtual function in the
base class and it is being overridden in the
derived class then we don’t need virtual
keyword in the derived class, functions are
automatically considered as virtual
functions in the derived class.
Virtual Table
If a class contains a virtual function then
compiler itself does two things:
If object of that class is created then a virtual
pointer(VPTR) is inserted as a data member
of the class to point to VTABLE of that class.
For each new object created, a new virtual
pointer is inserted as a data member of that
class.
Irrespective of object is created or not, a
static array of function pointer called
VTABLE where each cell contains the address
of each virtual function contained in that class
Virtual Table
Pure Virtual Function
A pure virtual function (or abstract function)
in C++ is a virtual function for which we
don’t have implementation, we only declare
it.
A pure virtual function is declared by
assigning 0 in declaration.
Syntax:-
virtual void show() = 0;
Example:-
Similarity between Virtual
Function & Pure Virtual Function
These are the concepts of Run-time
polymorphism.
Prototype i.e. Declaration of both the
functions remains the same throughout the
program.
These functions can’t be global or static.
Difference between Virtual
Function & Pure Virtual Function
Virtual Function Pure Virtual Function
A virtual function is a member function of A pure virtual function is a member
base class which can be redefined by function of base class whose only
derived class. declaration is provided in base class and
should be defined in derived class
otherwise derived class also becomes
abstract.
Classes having virtual functions are not Base class containing pure virtual function
abstract. becomes abstract.
Syntax:- Syntax:-
virtual<func_type><func_name>() virtual<func_type><func_name>()
{ = 0;
// code
}
Definition is given in base class. No definition is given in base class.
Base class having virtual function can be Base class having pure virtual function
instantiated i.e. its object can be made. becomes abstract i.e. it cannot be
instantiated.
Important Points related to
pure virtual function
1) A class is abstract if it has at least one
pure virtual function.
2)We can have pointers and references of
abstract class type.
3) If we do not override the pure virtual
function in derived class, then derived class
also becomes abstract class.
4) An abstract class can have constructors.
Virtual Destructor
Deleting a derived class object using a
pointer of base class type that has a non-
virtual destructor results in undefined
behaviour.
To correct this situation, the base class
should be defined with a virtual destructor.
#include <iostream>
using namespace std;
class A
{
public:
~A()
{
cout<<"class base Destructor"<<endl;
}
};
class B:public A
{ Output:
public: class base Destructor
~B()
{
cout<<"class derived
Destructor"<<endl;
}
};
int main()
{
A* b=new B;
delete b;
}
#include <iostream>
using namespace std;
class A
{
public:
virtual ~A()
{
cout<<"class base
Destructor"<<endl;
}
};
class B:public A
{
public:
~B() Output:
{ class derived Destructor
cout<<"class derived Dest"<<endl; class base Destructor
}
};
int main()
{
A* b=new B;
delete b;
}
Abstract base class
Abstract Class is a class which contains at least one Pure
Virtual function in it.
We can not declare the object of abstract class but we can
access it through inherited derived class object. We can
create a reference or pointer variable of abstract class we can
acess the normal member functions except pure virtual
function.
By using derived class function we can access the abstract
class.
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.
Syntax:
Class A
{
Public:
Virtual void show()=0;
};
int main()
#include <iostream> {
using namespace std; A* b;
class A B d;
{ d.disp();
public: d.show();
virtual void show()=0; b=&d;
void disp() b->show();
{ b->disp();
cout<<"class base"<<endl; return 0;
} }
};
class B:public A
{
public:
void show()
{
cout<<"class derived"<<endl;
}
};
Output:
class base
class derived
class derived
class base
Thank You