Module 3 Polymorphism
Module 3 Polymorphism
Runtime 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.
{
Complex c1(10, 5), c2(2, 4);
Complex c3 = c1 + c2; // An example call to "operator+"
c3.print();
}
Output:
12 + i9
In the above example the operator ‘+’ is overloaded. The operator ‘+’ is an addition
operator and can add two numbers(integers or floating point) but here the operator is made to
perform addition of two imaginary or complex numbers.
#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;
}
Output:
30
55
Let's see the simple example when the type of the arguments vary.
Output:
r1 is : 42
r2 is : 0.6
Operations that can be performed:
Arithmetic operations: + – * / %
Logical operations: && and ||
Relational operations: == != >= <=
Pointer operators: & and *
Memory management operator: new, delete []
When two or more methods in a class One method is in the parent class and the
have distinct parameters but the same other is in the child class when a function is
Definition
method name, this is known as function overridden, but they have the same
overloading. parameters and method name.
Behaviour defines several methods’ behaviours. changes the way the procedure behaves.
Scope of
They belong to the same category. They have a distinct range.
Function
Run time polymorphism: Run time polymorphism is achieved when the object's method is
invoked at the run time instead of compile time. It is achieved by method overriding which is
also known as dynamic binding or late binding.
base *bptr;
derived d;
bptr = &d;
bptr->print();
bptr->show();
return 0;
Output:
print() function is declared with virtual keyword so it will be bound at run-time (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 ).
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.
In late binding function call is resolved during runtime. Therefore compiler determines the type of
object at runtime, and then binds the function call.
The prototypes of a virtual function of the base class and all the derived classes must
be identical. If the two functions with the same name but different prototypes, C++ will
consider them as the overloaded functions.
We cannot have a virtual constructor, but we can have a virtual destructor
Consider the situation when we don't use the virtual keyword.
#include <iostream>
using namespace std;
class A
{
int x=5;
public:
void display()
{
std::cout << "Value of x is : " << x<<std::endl;
}
};
class B: public A
{
int y = 10;
public:
void display()
{
std::cout << "Value of y is : " <<y<< std::endl;
}
};
int main()
{
A *a;
B b;
a = &b;
a->display();
return 0;
Output:
Value of x is : 5
In the above example, * a is the base class pointer. The pointer can only access the base class
members but not the members of the derived class. Although C++ permits the base pointer to point
to any object derived from the base class, it cannot directly access the members of the derived
class. Therefore, there is a need for virtual function which allows the base pointer to access the
members of the derived class.
Let's see the simple example of C++ virtual function used to invoked the derived class in a
program.
#include <iostream>
{
public:
virtual void display()
{
cout << "Base class is invoked"<<endl;
}
};
class B:public A
{
public:
void display()
{
cout << "Derived Class is invoked"<<endl;
}
};
int main()
{
A* a; //pointer of base class
B b; //object of derived class
a = &b;
a->display(); //Late Binding occurs
}
Output:
A virtual function is not used for performing any task. It only serves as a placeholder.
When the function has no definition, such function is known as "do-nothing" function.
The "do-nothing" function is known as a pure virtual function. A pure virtual
function is a function declared in the base class that has no definition relative to the
base class.
A class containing the pure virtual function cannot be used to declare the objects of its
own, such classes are known as abstract base classes.
The main objective of the base class is to provide the traits to the derived classes and
to create the base pointer used for achieving the runtime polymorphism.
#include <iostream>
using namespace std;
class Base
{
public:
virtual void show() = 0;
};
class Derived : public Base
{
public:
void show()
{
std::cout << "Derived class is derived from the base class." << std::endl;
}
};
int main()
{
Base *bptr;
//Base b;
Derived d;
bptr = &d;
bptr->show();
return 0;
}
Output:
In the above example, the base class contains the pure virtual function. Therefore, the base class
is an abstract base class. We cannot create the object of the base class.
It is less flexible as mainly all the things It is more flexible as all the things execute
execute at the compile time. at the run time.