C++ Polymorphism

C++ Polymorphism is one of the most important feature of Object Oriented Programing OOP. In the word Polymorphism, poly means many and morph means form. Polymorphism means the phenomenon of having many forms. In C++ programming language, C++ polymorphism refers to the phenomenon where there are multiple classes in a code and classes relate to each other through inheritance. C++ Polymorphism occurs when different implementations of a function with same name exists. The function invoked depends on the type of object calling the function.

Classes and Inheritance are the prerequisite for C++ Polymorphism. According to inheritance, child class can inherit some or all members of its parent class. A real life example of polymorphism is water. Water can be in solid (ice), liquid (water) and gaseous (water vapors) states. The properties of water in theses three states is different but its composition is same. This is called polymorphism.

The below example shows polymorphism in which, Object is the parent class, RectangleObj and TraingleObj are child classes. The function findArea() has different implementation for the object of each child class.

#include <iostream>
using namespace std;
class Object {
   public:
      Object(int l = 0, int b = 0)
      {
         length = l;
         breadth = b;
      }
      int findArea()
      {
          cout << "Area of Parent Class object is:" << endl;
          return 0;
      }
   protected:
      int length;
      int breadth;
};
class RectangleObj: public Object {
   public:
      RectangleObj( int l = 0, int b = 0):Object(l, b) { }
      
      int findArea () { 
         cout << "Area of Rectangle class object is :" <<endl;
         return (length * breadth); 
      }
};
class TriangleObj: public Object {
   public:
      TriangleObj( int l = 0, int b = 0):Object(l, b) { }
      
      int findArea () { 
         cout << "Area of Triangle class object is :" <<endl;
         return (length * breadth / 2); 
      }
};
// Driver program
int main() {
   Object *obj;
   RectangleObj rec(5, 9);
   TriangleObj tri(3, 7);
   obj = &rec;
   obj->findArea();
   obj = &tri;
   obj->findArea();
   return 0;
}

The output of the above code after compilation is:

Types of C++ Polymorphism

There are two types of polymorphism as mentioned below:

  • Compile time Polymorphism
  • Run time Polymorphism

Compile time Polymorphism

Compile time polymorphism uses Function Overloading and Operator Overloading methods.

Function Overloading

A number of functions having same name but different parameters are overloaded functions. And this phenomenon is called Function Overloading. Multiple functions can achieve the phenomenon of overloading either by varying number of parameters, or varying type of parameters or both.

The code below shows function overloading example. The code contains a class Addition that defines three types of Sum() functions. All these sum functions are overloaded functions. The first sum() function takes the sum of two integer numbers. The second sum() function takes the sum of two decimal numbers. The third sum() function takes the sum of an integer and a decimal number.

The type of function called depends on the type of arguments with function name entered by programmer. When programmer enters integer type parameters with function name, then the first function is called. When programmer enters two decimal type parameters with function name, then the second function is called. Similarly when programmer enters an integer type and a decimal type parameter with function name, then the third function is called

#include <iostream>
#include <string>
using namespace std;
class Addition 
{ 
    public: 
    void sum(int x, int y) 
    { 
        int z;
        z = x + y;
        cout << "Sum of two integer values is " << z << endl; 
    } 
    void sum(double x, double y) 
    { 
        double z;
        z = x + y;
        cout << "Sum of two decimal values is " << z << endl; 
    } 
    void sum(int x, double y) 
    { 
        double z;
        z = x + y;
        cout << "Sum of an integer and a decimal values is " << z << endl; 
    } 
}; 
  
int main() { 
    Addition obj; 
    obj.sum(70, 8); 
    obj.sum(5.132, 3.142); 
    obj.sum(8,6.4); 
    return 0; 
}  

The output of the above code after compilation is:

Operator Overloading

Just like function overloading, C++ also allows Operator Overloading. In Operator Overloading, a single operator can act differently depending on the type of its operands. For example, the operator ‘+’ is used for both integers and strings and it works differently for both. When placed between two integer operands, the addition operator ‘+’ adds the two integers. While when placed between two string operands, it concatenates them.

The code below shows Operator Overloading example. In the below code, programmer uses the operator ‘+’ to take the sum of two complex numbers. In C++ programming language, + operator is used to take sum of integer or float numbers. Complex numbers have two parts. One part is the real part and the other part is imaginary part.

The code contains an addition class that has two private variables ‘r’ and ‘i’. ‘r’ being the real part and ‘i’ being the imaginary part. The program overwrites the operator + to take sum of two objects of the class Addition. This is called operator overloading.

#include <iostream>
#include <string>
using namespace std;
class Addition { 
private: 
    int r, i; 
public: 
    Addition(int num1 = 0, int num2 =0)  {r = num1;   i = num2;} 
    Addition operator + (Addition const &complex_num) { 
         Addition sum; 
         sum.r = r + complex_num.r; 
         sum.i = i + complex_num.i; 
         return sum; 
    } 
    void display() { cout << "The sum of two complex numbers is: "
    << r << " + i" << i << endl; } 
}; 
   
int main() 
{ 
    Addition c_num1(15, 25), c_num2(22, 34); 
    Addition c_num3 = c_num1 + c_num2;
    c_num3.display();
} 

Run time Polymorphism

Run time polymorphism uses the phenomenon of Function Overriding.

Function Overriding

Function overriding is a part of inheritance. It occurs when the function of child class overrides the function definition of parent class. The child class has its own definition for one of the member functions of parent class. The parent class has one virtual function that can be overridden. The function can be either virtual or pure virtual.

Virtual Function

The virtual function has a keyword virtual and is present in parent class. The virtual function provides dynamic linkage or late binding. It links the function and its definition to the related object. This means that the function to be called depends on the type of the object.

The below code has a parent class Parent. The parent class has a virtual function display() and a non virtual function print(). There is a child class Child that has its own different definition for the virtual function. The driver program creates an object obj1 of parent class and an object obj2 of child class. The parent class object points to the child class object.

In the statement obj1->display(); the display function is binded to the object on run time. That is why it is called Run Time Polymorphism using virtual function. Since print() is non virtual function so in the statement obj1->print(); the object is binded to the function on compile time.

#include <iostream>
using namespace std;
class Parent 
{ 
public: 
    virtual void display() 
    { cout<< "Parent class virtual function is called." <<endl; } 
    void print() 
    { cout<< "Parent class print function is called" <<endl; } 
}; 
class Child:public Parent
{ 
public: 
    void display() 
    { cout<< "Child class display function is called" <<endl; }    
    void print() 
    { cout<< "Child class print function is called" <<endl; } 
};   
//Driver Program
int main()  
{ 
    Parent *obj1; 
    Child obj2; 
    obj1 = &obj2; 
    obj1->display();  
    obj1->print();  
    return 0; 
}  

The output of the above code after compilation is:

Pure Virtual Function

Pure virtual functions help achieve C++ Polymorphism. Pure virtual function contains virtual keyword in its declaration. The pure virtual function declaration also includes “=0” specification. The syntax for declaring a pure virtual function is as follows:virtual return_type func_name() = 0;

Here virtual is the keyword, return_type is the return type of function. The func_name is the name of function. For example, the function below is a pure virtual function.virtual void virFunc() = 0;

In the above example, virFunc() is a pure virtual function. The pure virtual function can also be an abstract function as it has no body.

For example, the code below shows how to declare a pure virtual function in an abstract class and how to define it in different ways in derived classes to achieve C++ Polymorphism.

#include <iostream>
using namespace std;
class Object {
   public:
      virtual int findArea() = 0;
      void setLen(int l) {
         length = l;
      }
      void setBred(int b) {
         breadth = b;
      }
   protected:
      int length;
      int breadth;
};
class RectangleObj: public Object {
   public:
      int findArea() { 
         return (length * breadth); 
      }
};
class TriangleObj: public Object {
   public:
      int findArea() { 
         return (length * breadth)/2; 
      }
};
 int main(void) {
   RectangleObj R1;
   TriangleObj  T1;
   R1.setLen(6);
   R1.setBred(9);
   cout << "Area of Rectangular object is: " << R1.findArea() << endl;
   T1.setLen(3);
   T1.setBred(8);
   cout << "Area of Trianglur object is: " << T1.findArea() << endl; 
   return 0;
}

In the above code, there is an Abstract class Object. It has two derived classes RectangleObj and TriangleObjfindArea() is a pure virtual function. For the class RectangleObj it has different implementation and for the object of TriangleObj, it has different implementation of finding area. The objects of derived classes (T1 and R1) access the pure virtual function. The output of the above code after compilation is: