What is polymorphism?

Polymorphism is an object-oriented programming concept that refers to the ability of a variable, function, or object to take on multiple forms. In a programming language exhibiting polymorphism, class objects belonging to the same hierarchical tree (inherited from a common parent class) may have functions with the same name, but with different behaviors.

Example

The classic example is of the Shape class and all the classes that are inherited from it, such as:

  • Rectangle

  • Triangle

  • Circle

svg viewer

Code

Below is an example of Polymorphism:

class Shape
{
public:
Shape(){}
//defining a virtual function called Draw for shape class
virtual void Draw(){cout<<"Drawing a Shape"<<endl;}
};
class Rectangle: public Shape
{
public:
Rectangle(){}
//Draw function defined for Rectangle class
virtual void Draw(){cout<<"Drawing a Rectangle"<<endl;}
};
class Triangle: public Shape
{
public:
Triangle(){}
//Draw function defined for Triangle class
virtual void Draw(){cout<<"Drawing a Triangle"<<endl;}
};
class Circle: public Shape
{
public:
Circle(){}
//Draw function defined for Circle class
virtual void Draw(){cout<<"Drawing a Circle"<<endl;}
};
int main() {
Shape *s;
Triangle tri;
Rectangle rec;
Circle circ;
// store the address of Rectangle
s = &rec;
// call Rectangle Draw function
s->Draw();
// store the address of Triangle
s = &tri;
// call Traingle Draw function
s->Draw();
// store the address of Circle
s = &circ;
// call Circle Draw function
s->Draw();
return 0;
}

Explanation

In the example above,

  • We used virtual keyword while defining the Draw() functions as a virtual function is a member function which when declared in the base class can be re-defined (Overriden) by the derived classes.

  • At run time the compiler looks at the contents of the pointer *s.

  • Since, the addresses of objects of tri, rec, and circ are stored in *s the respective Draw() function is called.

As you can see, each of the child classes has a separate implementation for the function Draw(). This is how polymorphism is generally used.

Types of polymorphism

  • Compile time polymorphism

    • Example: Method overloading

  • Runtime polymorphism

    • Example: Method overriding

svg viewer

Let's see the implementation of compile time polymorphism and run-time polymorphism.

Compile-time polymorphism (method overloading)

In the example below, We implement the method overloading which is a form of compile-time polymorphism in the Calculator class. we overload add method with different parameter lists.

#include <iostream>
class Calculator {
public:
// Method to add two integers
int add(int a, int b) {
return a + b;
}
// Method to add three integers
int add(int a, int b, int c) {
return a + b + c;
}
};
int main() {
Calculator calc;
// Method overloading - compiler determines which method to call based on arguments
std::cout << "Result 1: " << calc.add(5, 10) << std::endl;
std::cout << "Result 2: " << calc.add(5, 10, 15) << std::endl;
return 0;
}

Run-time polymorphism (method overriding)

In this example below, Animal, Dog, and Cat classes demonstrate method overriding, a form of run-time polymorphism. Even though the reference is of type Animal, the actual method called is determined by the type of object instantiated.

#include <iostream>
using namespace std;
class Animal {
public:
virtual void makeSound() {
cout << "Animal makes a sound" << std::endl;
}
};
class Dog : public Animal {
public:
void Sound() override {
cout << "Dog barks" << std::endl;
}
};
class Cat : public Animal {
public:
void makeSound() override {
cout << "Cat meows" << std::endl;
}
};
int main() {
Animal* dog = new Dog(); // Runtime polymorphism - pointer of parent class, object of child class
Animal* cat = new Cat();
dog->Sound(); // Calls Dog's makeSound method
cat->Sound(); // Calls Cat's makeSound method
delete dog;
delete cat;
return 0;
}

Advantages of polymorphism:

  • It helps programmers reuse code and classes once written, tested, and implemented.

  • A single variable name can be used to store variables of multiple data types (float, double, long, int, etc).

  • It helps compose powerful, complex abstractions from simpler ones.

Copyright ©2024 Educative, Inc. All rights reserved