How to implement polymorphism in C++

In this tutorial, we will see what is polymorphism and then understand how to implement it in C++.

Introduction to Polymorphism in C++

The word polymorphism is made up of two words poly and morph which means multiple forms. Polymorphism can be defined as the ability of a message to take on multiple forms. And this message corresponds to a function or operator in C++. Thus, in C++, we can use the same function or the same operator to perform different tasks. Polymorphism is an important concept in OOP.

There are two different types of polymorphism in C++.

Compile time polymorphism in C++

Compile time polymorphism is also known as early data binding or static polymorphism. It is achieved when the object’s method is invoked at the compile time. Compile time polymorphism is achieved by function overloading and method overloading.

Function overloading:

In this case, we use the same name for more than one function and pass different parameters each time. The functions to be invoked is known at compile time and is invoked by the number and type of parameters passed. It increases readability of the program as we use the same name for the same action.

Now let us see an example where we change the number of arguments of area().

#include<iostream>
using namespace std;
class cal
{	public:
	static int area(int l,int b)
	{
		return l*b;
	}
	static int area(int b)
	{
		return b*b;
	}
	
};
int main()
{ cal c;
  cout<<c.area(5,10)<<"\n";
  cout<<c.area(5)<<"\n";
}

OUTPUT:

50

25

In the first case, the first method is called as two integers are passed as parameters. And in the second case, the second method is called as only one integer is passed as the parameter.

Operator overloading:

Like function overloading, we can also overload operators and enhance the functionality of operators in C++. Operator overloading in C++ is to specify more than one definition for an operator in the same scope.

Let us see an example.

#include<iostream>
using namespace std;
class complex{
  private:
   int r,i;
  public:
  complex()
   {
     r=0;
     i=0;
   }
   complex(int x, int y)
   {
     r=x;
     i=y;
   }
   void display()
   { cout<<r<<"+"<<i<<"i"<<endl;
  }
};
void main()
{ 
    int x=5;
    int y=4;
    int z= x+y;
    cout<<z;

}

OUTPUT:

9

Here ‘+’ knows what to do. It takes the value of x and simply adds it with the value of y and gives the output as 9.

Now, let us create three objects of the user defined class complex.

void main()
{ 	complex c1(5,4);
        complex c2(2,4);
        complex c3;
 	c3=c1+c2; 
}

We are expecting from the above code that c1 adds the real part of c1 with that of c2 and imaginary part of c1 to that of c2.
But it will show an error as the ‘+’ operator does not know the data type of c1 and c2 and hence, there will be no match for the operator ‘+’.
Hence, we will overload the operator ‘+’ in a way that it will understand what to do with c1 and c2.
So, let us see how to overload the operator + through this code.

complex operator +(complex c)
{ complex t;
  t.r=r+c.r;
  t.i=i+c.i;
  return t;
}

We see that operator overloading is basically a special type of function placed inside the main class where we need to use the keyword ‘operator’ followed by the operator to be overloaded(+ in this case).
Here, the line ‘c3=c1+c2’ can be equated as ‘c3=c1.add(c2)’.
c1 object is calling the function add and c2 is passed as a parameter. The r and i data member is for c1. c2 is passed as a parameter c which is acting as the c.r and c.i part for real and imaginary part respectively. ‘temp’ is created to hold the addition values and its return type is complex.
So, the addition of c1 and c2 will return a complex object which is stored in c3.

The complete code is as follows:

#include<iostream>
using namespace std;
class complex{
  private:
   int r,i;
  public:
  complex()
   {
     r=0;
     i=0;
   }
   complex(int x, int y)
   {
     r=x;
     i=y;
   }
   void display()
   { cout<<r<<"+"<<i<<"i"<<endl;
  }
  
  complex operator +(complex c)
  {       complex t;
  	  t.r=r+c.r;
  	  t.i=i+c.i;
 	  return t;
  }

};
void main()
{ 	complex c1(5,4);
        complex c2(2,4);
 	 complex c3;
 	 c3=c1+c2; 
 	 c3.display();
}

OUTPUT:

7+8i

The output shows us that the operator is overloaded successfully.
In this way we can overload almost any operator in C++. But there are few operators which cannot be overloaded – scope operator(::), size of, member selector(. ), member pointer selector(*), ternary operator(?:).

Thus, we have seen how operators and functions can be overloaded and used to implement compile time polymorphism in C++.

Next let us see runtime polymorphism.

Runtime polymorphism in C++

Runtime polymorphism is also known as late data binding or dynamic polymorphism. It is achieved when the function to be invoked is known at run time. Runtime polymorphism is achieved by function overriding in C++.

Function overriding:

If a base class and a derived class contains a function with the same name, it is known as function overriding in C++. It means the derived class redefines the base class function. Function overriding involves inheritance.

Let us see an example to understand function overriding.

#include<iostream>
using namespace std;
class car{
  public:
    void show()
    {
    cout<<"car";
    
    }
};
class maruti: public car
{
  public:
    void show()
    {
    cout<<"maruti";
    
    }
};
void main()
{
  maruti m = maruti();
  m.show();
}

OUTPUT:

maruti

Here, we created an object of the derived class maruti() and called the member function show() which exists in both classes. The member function of the derived class is invoked and the function of the base class is ignored.

Runtime polymorphism is achieved by using the reference variable of the base class to refer the objects of the derived class.

Let us see another example.

#include<bits/stdc++.h>
using namespace std;
class car{
  public:
    void print()
    {
    cout<<"base\n";
    
    }
    virtual void show()
    {
    cout<<"car\n";
    
    }
};
class maruti: public car
{
  public:
    void print()
    {
    cout<<"derived\n";
    
    }
    void show()
    {
    cout<<"maruti\n";
    
    }
};
void main()
{
  car *c;
  maruti m;
  c=&m;
  c->show();
  c->print();
}

OUTPUT:

maruti

base

In the above example,  a base class pointer refers to a derived class object and the base class function gets executed when the base class pointer contains the address of the derived class object. But, when the base class function is made virtual( by declaring show() function with a virtual keyword in base class), the derived class’s version of the function is executed.

Hence, in this way polymorphism can be implemented in C++.

Also read:

Leave a Reply

Your email address will not be published. Required fields are marked *