In C++, the concept of "Polymorphism" originates from the Greek words "poly" + "morphs", translating to "many forms". This feature allows entities like functions and operators to exhibit different behaviors based on the context. By leveraging polymorphism, a single task can be executed through various approaches, making it a fundamental aspect of Object-Oriented Programming principles.
Simple Example of Polymorphism
Let's consider a basic illustration of polymorphism in C++ involving the + operator.
Example
#include <iostream>
using namespace std; //using standard namespace
int main() //Main Function
{
int a = 15; //initialize integer values
int b = 20;
string x = "poly"; //initialize string values
string y = "morphism";
cout << "The Value of a + b is: " << a + b <<endl;
cout << "The Value of x + y is: " << x + y;
return 0;
}
Output:
The Value of a + b is: 35
The Value of x + y is: polymorphism
Explanation
In this instance, we have utilized two plus (+) operators. The initial plus operator is employed for summing two integer values, while the second plus operator is utilized for merging two string operands.
Types of Polymorphism:
Polymorphism in C++ can be classified into two distinct types:
- Static Polymorphism
- Dynamic Polymorphism
Compile-Time Polymorphism
In C++, compile-time polymorphism is also referred to as early binding and static polymorphism. This type of polymorphism involves the compiler determining how the operator or function will behave based on the context. It allows for the existence of multiple functions sharing the same name but with varying parameter lists.
It is achieved through the utilization of function overloading and operator overloading.
a) Function Overloading
In C++, function overloading plays a significant role in the realm of object-oriented programming. This feature allows the creation of multiple functions with identical names but varying parameters. Function overloading can be achieved by adjusting the quantity or types of arguments within the functions.
To Read More: Function Overloading
Example of Compile-Time Polymorphism using Function Overloading
Let's consider an illustration to demonstrate the implementation of compile-time polymorphism through function overloading.
Example
#include <iostream>
using namespace std; //using standard namespace
class CppTutorial {
public:
// Function to multiply two integer point values
void multiplication(int x, int y) {
cout << "Integer Multiplication Result = " << x * y
<< endl;
}
// Function to multiply two floating point values
void multiplication(double x, double y) {
cout << "Double Float Result = " << x * y
<< endl ;
}
};
int main() //main function
{
CppTutorial obj;
obj.multiplication(12, 5); // calls show(int)
obj.multiplication(4.5, 2.5); // calls show(double)
return 0;
}
Output:
Integer Multiplication Result = 60
Double Float Result = 11.25
Explanation
In this instance, we are examining the class CppTutorial, which includes a pair of multiplication methods sharing a common name but accepting varying parameters. The initial multiplication method operates with integers, whereas the alternative one works with double values. Within the main function, invoking obj.multiplication(12, 5) triggers the integer implementation, whereas obj.multiplication(4.5, 2.5) triggers the floating-point implementation.
b) Operator Overloading
In C++, operator overloading refers to the process of defining custom meanings for operators when working with user-defined data types. This functionality is implemented by redefining operators like +, -, *, ==, <<, >, and others. To utilize operator overloading in C++, it is essential that at least one of the operands involved is a user-defined data type.
To Read More: Operator Overloading
C++ Compile-Time Polymorphism Example using Operator Overloading
Let's consider an instance to demonstrate the implementation of compile-time polymorphism through operator overloading.
Example
#include <iostream>
using namespace std; //using standard namespace
class CppTutorial_oper {
private:
int value;
public:
// Constructor to initialize value
CppTutorial_oper(int a) : value(a) {}
// Overload * operator
CppTutorial_oper operator * (const CppTutorial_oper& obj) {
return CppTutorial_oper(value * obj.value);
}
// Function to show value
void show() {
cout << "The Multiplication Result of Two Numbers is: " << value << endl;
}
};
int main() //Main function
{
CppTutorial_oper x(12);
CppTutorial_oper y(5);
CppTutorial_oper result = x * y; // Calls overloaded * operator
result.show();
return 0;
}
Output:
The Multiplication Result of Two Numbers is: 60
Explanation
In this instance, the multiplication operator () is redefined in the CppTutorialoper class to handle the multiplication operation between two instances. Each instance holds an integer value. The redefined operator accepts another CppTutorialoper instance as input, computes the product of their internal values, and generates a new instance with the outcome. Subsequently, the show method is employed to exhibit the product of the multiplication.
Run-Time Polymorphism
In C++, achieving run-time polymorphism involves invoking the object's method during runtime rather than compile time. This concept is also referred to as late binding or dynamic binding, facilitating method overriding in the derived class.
It is executed through the utilization of function overriding and virtual methods.
a) Function Overriding
In C++, function overriding represents a key object-oriented programming concept that allows a subclass to redefine a method inherited from its superclass. This functionality is essential for implementing dynamic polymorphism.
To enable overriding, the function within the parent class needs to be declared as virtual. Subsequently, in the child class, the function must possess identical name, return type, and parameters.
To Read More: Function Overriding
C++ Run-Time Polymorphism Example using Function Overriding
Let's consider an illustration to apply runtime polymorphism through function overriding.
Example
#include <iostream>
using namespace std; //using standard namespace
class Shape // base class
{
public:
virtual void draw() // virtual function
{
cout<<"drawing..."<<endl;
}
};
class Rectangle: public Shape // derived class inheriting shape class
{
public:
void draw() override
{
cout<<"drawing rectangle..."<<endl;
}
};
class Circle: public Shape //derived class
{
public:
void draw() override
{
cout<<"drawing circle..."<<endl;
}
};
int main(void) //main function
{
Shape *s; // base class pointer.
Shape sh; // base class object.
Rectangle rect; //Derived class object
Circle circ;
s=&sh;
s->draw();
s=▭
s->draw();
s= ˆ
s->draw();
}
Output:
drawing...
drawing rectangle...
drawing circle...
Explanation
In this instance, we've created a foundational class called Shape containing a virtual method draw. Subsequently, the subclasses Rectangle and Circle have been employed to redefine the draw method. Within the primary function, a pointer s of the base class is employed to depict various objects at varying intervals.
b) Virtual Function
In C++, a virtual function is a method that is defined in the base class. By using the virtual keyword, we can define a virtual function in the base class. When a method is marked as virtual in the base class and called using a base class pointer, it will execute the method from the derived class. The virtual function in the base class enables the derived class to replace or override that function.
To Read More: Virtual Function
C++ Run-Time Polymorphism Example using Virtual Function
Let's consider an illustration to demonstrate the implementation of run-time polymorphism using Virtual Functions.
Example
#include <iostream>
using namespace std; //using standard namespace
class Animal {
public:
virtual void Ani_color() {
cout << "Animal Color Black" << endl;
}
};
class Dog : public Animal {
public:
void Ani_color() {
cout << "Animal Color Gray" << endl;
}
};
int main() //main function
{
Dog dog1;
//pointer of Base type
Animal* ani1 = &dog1;
//calls member function of Derived class
ani1->Ani_color();
return 0;
}
Output:
Animal Color Gray
Explanation
In this illustration, we've used a base class named Animal that includes a virtual method named Anicolor, which is redefined in the subclass Dog. Within the main function, a pointer of type Animal* is employed to reference an instance of the Dog class. When the Anicolor method is invoked through this base class pointer, it triggers the redefined implementation in the Dog class due to the presence of the virtual keyword.
Differences between Compile-Time and Run-Time polymorphism
Several variances between Compile-Time and Run-Time Polymorphism in C++ are outlined below:
| Compile time polymorphism | Run time polymorphism |
|---|---|
| The function to be called is known as the compile time. | The function to be called is known as the run time. |
| It is also known as overloading, early binding and static binding. | It is also known as overriding, Dynamic binding and late binding. |
| Overloading is a compile-time polymorphism where multiple methods have the same name but with a different number of parameters. | Overriding is a run time polymorphism where multiple methods have the same name and number of parameters. |
| It is implemented by function overloading and operator overloading. | It is implemented by virtual functions and pointers. |
| It offers fast execution at the compile time. | It offers slow execution at the run time. |
| It is less flexible because all functions execute at the compile time. | It is more flexible because all function execute at the run time. |
C++ Polymorphism MCQs
1) Which type of polymorphism is implemented by function overriding?
- Run-time polymorphism
- Compile-time polymorphism
- Dynamic polymorphism
- Static polymorphism
2) Which of the following keywords is used to implement the run-time polymorphism in C++?
- virtual
- polymorphic
- final
- override
3) What will be the output of the given program?
#include <iostream>
using namespace std; //using standard namespace
class Employee
{
public : int emp_id;
void show()
{
cout<<"It is the base class" <<endl;
}
};
class department : public Employee{
public :
void show()
{
cout<<"It is the derived class";
}
};
int main() //main function
{
Employee emp1;
department dept;
emp1.show();
dept.show();
};
- It is the derived classIt is the base class
- It is the derived class It is the base class
- It is the base class It is the derived class
- It is the base classIt is the derived class
It is the derived class
4) Which one of the following options shows the polymorphism in C++?
- Overloading &&
- Overloading +=
- Overloading ||
- Overloading <<
5) Which one of the following options is the main advantage of polymorphism in C++?
- Code Optimization
- Type Safety
- Code Reusability
- Memory Efficiency