Polymorphism in C++

Types of Polymorphism in C++

Types of Polymorphism in C++

Polymorphism is the ability of something to be displayed in multiple forms. In programming context, polymorphism means that some programming code or functionality or objects behave differently in different contexts or convey messages in different forms. Polymorphism occurs when there is a hierarchy of classes and they are related by inheritance.

Let’s take a real life scenario; a person at the same time can perform several duties as per demand, in the particular scenario. Such as, a man at a same time can serve as a father, as a husband, as a son, and as an employee. So, single person possess different behaviors in respective situations. This is the real life example of polymorphism. It is one of the important features of OOP (Object Oriented Programming).

The design patterns show how to use primitive techniques such as objects, inheritance, and polymorphism.

Definition of Polymorphism

Polymorphism is defined more or less same in different text books.

What virtual functions provide is called runtime polymorphism, and what templates offer is called compile time polymorphism or parametric polymorphism.

The C+ + Programming Language Third Edition by Bjarne Stroustrup

Polymorphism essentially means that a given function call can be bound to different implementations, depending on compile-time or runtime contextual issues.

Modern C++ Design: Generic Programming and Design Patterns Applied by Andrei Alexandrescu

Polymorphism is the third essential feature of an object-oriented programming language, after data abstraction and inheritance… Polymorphism allows improved code organization and readability as well as the creation of extensible programs that can be “grown” not only during the original creation of the project, but also when new features are desired.

Thinking in Java Fourth Edition by Bruce Eckel

Polymorphism simplifies the definitions of clients, decouples objects from each other, and lets them vary their relationships to each other at run-time. The ability to substitute objects of matching interface for one another at run-time.

Design Patterns: Elements of Reusable Object-Oriented Software by by Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides, Grady Booch

Polymorphism allows subclasses to distinguish themselves from one another…the term polymorphism is used to describe the situation in which a single statement can take on different definitions.

Calvin College

What are the types of Polymorphism in C++

In C++ Polymorphism is mainly divided into two types

1) Compile Time Polymorphism and

2) Runtime Polymorphism

Types of Polymorphism in C++

Compile Time Polymorphism

This type of polymorphism is also known as static polymorphism and is achieved by overloading a function, method or an operator. Generally in C++, what templates offer is called compile time polymorphism or
parametric polymorphism.

Compile Time Polymorphism in C++

What is Function Overloading?

When multiple functions are used at different places with same name but different parameters then these functions are known as overloaded function. Functions can be overloaded in two ways:

1) By change in number of arguments

2) By change in type of arguments

Let’s consider an example.

#include <iostream.h>

using namespace std;

class mycplus
{
    public:
      // function # 01: with 1 parameter of type int
    void function(int a)
    {
        cout << "value of a is " << a << endl;
    }
      // function # 02: having same name but a double parameter
    void function(double a)
    {
                   cout << "value of a is " << a << endl;
    }
        // function # 03: with same name but 2 int parameters
    void function(int a, int b)
    {
        cout << "value of a and b is " << a << ", " << b << endl;
    }
};
 
int main() {
     
    mycplus obj;
      // The call of function will depend on the type of parameters 
     // passed
    //The first 'function with one int parameter' is called 
    obj.function(3);
     // The second 'function with a double parameter' is called
    obj.function(6.456);
     // The third 'function with 2 int parameters' is called
    obj.function(8,71);

    return 0;
} 

Output:

value of a is 3

value of a is 6.456

value of a and b is 8, 71

The above example perfectly explains the concept of function overloading, a single function/method named function acts differently in 3 different situations which is the property of polymorphism.

Operator Overloading

The second method of compile time polymorphism is operator overloading. For example, we can make the operator (‘+’) for string class to concatenate two strings.  The general concept regarding “+” operator is that it is an addition operator whose task is to sum up two operands. But here in polymorphism, it will be used for a different purpose.

So, a single operator ‘+’ when placed between strings, concatenate them and when placed between integer operands, adds them. Let’s take an example of illustrating Operator Overloading using C++.

#include<iostream>
using namespace std;
class Testop {
private:
    int real, imag;
public:
    Testop(int r = 0, int i =0): real(r), imag(i)  {}
      // The following function will automatically called when '+'
// is used with between two Testop objects
    Testop operator + (Testop const &obj) {
         Testop obj1;
         obj1.real = real + obj.real;
         obj1.imag = imag + obj.imag;
         return obj1;
    }
    void print() 
{ 
cout << "The result of adding two complex numbers by operator overloading is  " << real << " + i" << imag << endl; 
}
};
  
int main()
{
    Testop t1(12, 15), t2(1, 6);
    Testop t3 = t1 + t2; // call to "operator +"
    t3.print();
}

Output:

The result of adding two complex numbers by operator overloading is 13 + i21

In above mentioned example the “+” operator is overloaded. Here the operator is made to perform addition of two complex numbers.

Testop operator + (Testop const &obj)

is called automatically when the operator “+” is used in the main function.

Here it is important to mention that, operator overloading can be done on both unary as well as binary operators.

Runtime polymorphism

The second type of polymorphism is runtime polymorphism. It can be achieved by using Function Overriding or method overriding i.e. the specific function to call will be determined at runtime based on object’s dynamic type. Generally in C++, what virtual functions provide is called runtime polymorphism.

Runtime polymorphism in C++

What is Function Overriding?

Function overriding is giving another definition to an existing method with same parameters or we can say that a method has same prototype in base as well as derived class.

For example: when an inherited class in C++ has a different definition for one of functions of the base class then here the function of base class is said to be overridden.

#include <bits/stdc++.h>
using namespace std;
 // Parent class
class Base
{
    public:
    void result()
    {
        cout << "Result method of Base class is called" << endl;
    }
};
 
// Following is the Derived class having similar result() method as of 
//base class
class Derive : public Base
{
    public:
     
    // definition of a result method already exists in Base class
    void result()
    {
        cout << "The result method of derived class is called " << endl;
    }
     
};
 
int main() 
{
    //instantiating object of Base class
    Base obj;
         //object of child class
    Derive obj1 = Derive();
      
    // obj will call the result method in Base Class
    obj1.result();
     
    // obj1 will override the result method in Base
    // and call the result method in Derive class
    Obj1.result();
    return 0;
} 

Output:

Result method of Base class is called

The result method of derived class is called

In the above-mentioned example, the result () method of base class is overridden and redefined in the base class.

Runtime Polymorphism using Virtual Functions

Runtime polymorphism can also be achieved by virtual functions. A virtual Function is the member of base class and is overrides in the derived class. The syntax of a virtual function is to precede its declaration with keyword “virtual”.

Here are some c programs to demonstrate how virtual pointers, virtual tables and virtual functions work in C++

Virtual function actually tells the compiler to perform Dynamic Binding (resolves function call at runtime) on it.

#include <iostream>

using namespace std;

class Polygon {

  protected:

    int w , h;

  public:
    void set_values (int x, int y)
      { 
           w=x; h=y; 
       }
    virtual int area ()
      { 
         return 0; 
       }
};

class Rect: public Polygon {
  public:
    int area ()
      { 
        return w * h;
 }
};

class Tri: public Polygon {
  public:
    int area ()
      { 
         return (w * h / 2);
     
        }
};

int main () {
  Rect rec;
  Tri trg;
  Polygon poly;
  Polygon * ppoly1 = &rec;
  Polygon * ppoly2 = &trg;
  Polygon * ppoly3 = &poly;
  ppoly1->set_values (11,25);
  ppoly2->set_values (11,25);
  ppoly3->set_values (11,25);
  cout << ppoly1->area() << '\n';
  cout << ppoly2->area() << '\n';
  cout << ppoly3->area() << '\n';

  return 0;
}

Output:

275
137

In the above mentioned example, there are three classes i.e. Polygon, Rectangle and Triangle and all have the same functions set_values() and area() and same member variables w, h.

Function main declares three pointers, ppoly1, ppoly2 and ppoly3 to Polygon. The first two pointers are assigned the addresses of rec and trg that are objects of Rect and Tri. This type of assignment is valid, as both classes Rect and Tri are derived from Polygon.

*ppoly1 and *ppoly2 is dereferencing of both pointers and enables us to access the members of their pointed objects. To understand the concept, consider the following example,

ppoly1->set_values (11,25);  is equivalent to & rec.set_values (11,25);

In base class, the member function “area” is declared as virtual and is later redefined in both of the derived classes Rect and Tri. So, it allows us to access the non-virtual members of derived classes via a reference of the base class. But if the keyword “virtual” is removed from the declaration of area in the base class, all three calls to area would return zero.

The virtual keyword allows the members of a derived class to be called appropriately who have the same name as one of the member of the base class. More accurately when the type of the pointer is a pointer to the parent class, which is pointing to an instance of the derived class, as you can see in the above example.

M. Saqib: Saqib is Master-level Senior Software Engineer with over 14 years of experience in designing and developing large-scale software and web applications. He has more than eight years experience of leading software development teams. Saqib provides consultancy to develop software systems and web services for Fortune 500 companies. He has hands-on experience in C/C++ Java, JavaScript, PHP and .NET Technologies. Saqib owns and write contents on mycplus.com since 2004.
Related Post