Polymorphism in C++

Polymorphism in C++​

Polymorphism basically means having multiple existent forms in the program, A simple code may behave differently in different situations. For example, we have only one identity, to some we are friends, or father, student, employee etc.

polymorphism

How Polymorphism works in C++

In C++, polymorphism, generally happens because of classes objects and events are related with inheritance and hierarchy. Lets see what’s polymorphism in detail below –

Polymorphism is of two types –

  • Compile time polymorphism (demonstrates static/early binding)
    • Function Overloading
    • Operator Overloading
  • Run time polymorphism (demonstrates dynamic/late binding)
    • Function Overriding (Achieved with help of virtual keyword)
Polymorphism in C++

Compile Time Polymorphism

Function Overloading

This happens when in a given program there are multiple functions with the same name but different arguments inside it or different parameters.

For example –

#include<iostream>
using namespace std;

class myClass {
    public:
    void myFunction(int a)
    {
        cout << "Accepted integer value " << a << endl;
    }
  
    void myFunction(double a) {
        cout << "Accepted double value " << a << endl;
    }
  
    void myFunction(int a, int b) 
    {
        cout << "Accepted multiple values, Value1:" << a << endl;
        cout << "Accepted multiple values, Value2:" << b << endl;
    }
};

int main() {
    myClass myclassObj;

    // will go to function with int as passed on variable as value passed is int type
    myclassObj.myFunction(5);

    // will go to function with double 
    myclassObj.myFunction(500.263);

    // will go to function with multiple parameters
    myclassObj.myFunction(5,3);

    return 0;
}

Output –

Accepted integer value 5
Accepted double value 500.263
Accepted multiple values, Value1: 5
Accepted multiple values, Value2: 3

Now, in the above, the functions go to their correct argument type in myClass this is called function overloading.

Operator Overloading

Operator overloading is possible in C++, you can change the behaviour of an operator like +, -, & etc to do different things.

  • For example, you can use + to concatenate two strings.
  • Consider two strings s1 and s2, we can concatenate two strings s1 and s2 by overloading + operator as String s, s = s1 + s2; 

For Example – We know that ++x increments the value of x by 1. What if we want to overload this and increase the value by 100. The program below does that.

#include 
using namespace std;

class Test
{
    private:
    int count;

    public:
    Test(): count(101)
    { 
        //writing fuction name followed by data member and passed on value works like constructor
        // Test(): count(101) same as writing count = 101; here
    }

    // we write operator before overloading such operators
    void operator ++() 
    { 
        count = count+100; 
    }
  
    void Display() 
    {
        court << "Count: " << count; 
    }
};

int main()
{
    Test t;
  
    // this calls "function void operator ++()" function
    ++t; 
  
    t.Display();
  
    return 0;
}

Output

201

Operators that can be overloaded -

+ - * / % ^
& | ~ ! , =
< > <= >= ++ --
<< >> == != && ||
+= -= /= %= ^= &=
|= *= <<= >>= [] ()
-> ->* new new [] delete delete []

Operators that can't be overloaded -

:: .* . ?:

Runtime Polymorphism

There are two ways run time polymorphism may be achieved in C++

  • Function Overriding
  • Virtual Functions (Solves the problem of static resolution while working with pointers)

Note – This information is given wrong on Gks4Gks and tut point they have explained virtual functions instead at first.

Runtime Polymorphism using Function Overriding

In a case when a function is declared in both the parent class(Base Class) and child class(Derived Class).

  • To decide upon which function has to be called, the program will only know at the run time.
  • Let us look at the very simple program below to understand the basic
#include<iostream>
using namespace std;

// This is Parent class
class Parent
{
    public:
    void print()
    {
        cout << "Parent Class printing" << endl;
    }
};

// This is Child class
class Child : public Parent
{
    public:

    // as we see that it is already declared in the parent function
    void print()
    {
        cout << "Child Class printing" << endl;
    }
};

int main()
{
    //Creating object for parent class
    Parent parent_object;

    //Creating object for child class
    //No need to get conused here its same as Child object2;
    //We are just called a default constructor
    Child child_object = Child();

    // This will go to the parent member function
    parent_object.print();

    // This will however, go to child member function
    // overrides the parent function as the object is of the child class
    child_object.print();
  
    return 0;
}

Output

Parent Class printing
Child Class printing

What exactly happens at the backend?

Even though, the child class has inherited all the functions of the parent class and has the same function definition within itself. The call is made to function of the child class as the object is of the child class.

Runtime Polymorphism using Virtual Function

  • What if we create a pointer to the parent class
  • And assign it to the address of the base class object

Something such as this –

Parent *parent_object;

Child child_object;

parent_object = &child_object;

Now, we will expect the function called by parent_object to call the child object function right? Because the final address is pointed toward child_object location. Let us see what happens –

Code

#include<iostream>
using namespace std;

// This is Parent class
class Parent
{
    public:
    void print()
    {
        cout << "Parent Class printing" << endl;
    }
};

// This is Child class
class Child : public Parent
{
    public:

    // as we see that it is already declared in the parent function
    void print()
    {
        cout << "Child Class printing" << endl; 
    } 
};
int main()
{
    Parent *parent_object;
    Child child_object;
    parent_object = &child_object;

    // catch of the program is here
    // also as we are dealing with pointers instead of . we need to use -> 
parent_object->print();

// In the above program instead of using pointers we can write
// Parent parent_object = Child();
// parent_object.print();
// this would also give same results

return 0;
}

Output

Parent Class printing

Forcing Runtime Polymorphism using Virtual function

If we add a virtual keyword before the function in the parent(base) class we can force runtime polymorphism (Late binding).

Let us look with the code below –

Code

#include<iostream>
using namespace std;

// This is Parent class
class Parent
{
    public:
    // adding virtual keyword here
    virtual void print()
    {
        cout << "Parent Class printing" << endl;
    }
};

// This is Child class
class Child : public Parent
{
    public:

    // as we see that it is already declared in the parent function
    void print()
    {
        cout << "Child Class printing" << endl; 
}
};

int main()
{
Parent *parent_object;
Child child_object;
parent_object = &child_object;

// catch of the program is here
// also as we are dealing with pointers instead of . we need to use -> parent_object->print(); return 0; }

Output

Child Class printing