What are the Different Types of Polymorphism in C++?

Learn via video course
FREE
View all courses
C++ Course: Learn the Essentials
C++ Course: Learn the Essentials
by Prateek Narang
1000
5
Start Learning
C++ Course: Learn the Essentials
C++ Course: Learn the Essentials
by Prateek Narang
1000
5
Start Learning
Topics Covered

What is Polymorphism in C++?

Polymorphism is the process of using a function or an operator for more than one purpose. In other words, we can also say that polymorphism refers to the fact that the same entity can serve us in different ways in different scenarios.

It is one of the main pillars of object-oriented programming in C++ and the word "polymorphism" is derived from two words "poly" and "morphism" which means multiple forms or multiple states.

We can understand polymorphism with the help of an example, consider the '+' operator, which can be used to add two integers (6 + 4 = 10), and we can also use the same operator to concatenate two strings ("Hello" + "Boss!" = "Hello Boss!").

Here, the '+' operator is behaving differently in two different situations and is serving two different purposes of adding and concatenation.

Learn more about polymorphism in C++

What are the Different Types of Polymorphism in C++?

The polymorphism in C++ can be divided into two types : Compile-time polymorphism ( which can further be classified into function overloading and operator overloading) and run-time polymorphism (which can further be classified into function overriding and virtual function).

types-of-polymorphism2

We will look in detail at each type of polymorphism in the upcoming sections of this article.

Compile Time Polymorphism

In compile-time polymorphism, a function is called at the compile time. This type of polymorphism is also known as static binding or early binding. Function overloading and operator overloading are the two types of Compile time polymorphism and are used to accomplish compile-time polymorphism.

types-of-compile-time-polymorphism

Function Overloading

Function overloading is defined as the process of using the same function for different purposes. Here, the same function can be used to perform different tasks just by changing the function signature (number of arguments, type of arguments). It is an example of compile-time polymorphism because which function will get called is decided at compile time. Function overloading is one of the simplest types among other types of polymorphism in c++.

To understand function overloading, we can think of an example, where we have two functions having the same name as Add, and we can just provide different numbers of arguments to do our two different tasks. The code for this example is shown below:

OUTPUT:

As we can see from the above code, the same add function can be used to perform different tasks just by changing the number of arguments in the function parameter.

This helps increase the program's readability as the same action is achieved by using the same name of the function.

Operator Overloading

Operator overloading is defined as the process of assigning additional tasks to operators without altering the actual meaning of the operation.

We can make operators work for user-defined classes by providing the operators with a special meaning for a data type (this does not mean that we are changing the actual meaning of the operator, we are just adding an additional specialty to that operator). This ability is known as operator overloading.

Let's understand this with the help of an example,

Here, variables num1 and num2 are of types int and float, which are built-in data types. Hence the addition operator ‘+’ can easily work here and do the addition of the contents of num1 and num2. This is because the addition operator “+” is predefined to add variables of built-in data type only.

But, now consider the case:

In this example, we have 3 objects obj1, obj2, and obj3. Here, we are trying to add two objects obj1 and obj2, which are of user-defined type i.e. of type “class A” using the “+” operator. This is not actually allowed, because the addition operator “+” is predefined to operate only on built-in data types. And so the compiler will give an error in this case.

This is where the “Operator overloading” comes into the picture.

We can use the "+" operator to add class objects by using operator overloading, where we have to redefine the meaning of the "+" operator such that it adds two class objects.

Redefining the meaning of operators does not change their actual meaning; instead, they have been given additional meaning along with their existing ones. Basically, the idea is to give special meaning to an existing operator along with its original meaning.

Runtime Polymorphism

In runtime polymorphism, a function is called at the run time or at the time of program execution. This type of polymorphism is also known as dynamic binding or late binding. Function overriding and virtual functions are the different types of run-time polymorphism.

It is more flexible than compile-time polymorphism as the things are executed at run time.

types-of-run-time-polymorphism

Function Overriding

In function overriding, we give a new definition to the base class method or a function in the derived class. This means that we override the definition of the base class function in the derived class. Thus, we have two definitions of the same function, one in the base class and the other in the child or the derived class. The decision of choosing which function definition is to be called is decided at the run time. That is the reason we call it a type of ‘Runtime polymorphism’.

Let's consider the example below to understand function overloading:

The output of the above code is:

As we can see from the output above, the definition of the func function is redefined in the derived class. And thus, this is an example of function overriding.

Virtual Function

A virtual function is a base class member function, which is re-defined (overridden) by a derived class.

As runtime polymorphism is achieved only through a pointer (or reference) of base class type. A base class pointer can point to the objects of the base class as well as to the objects of the derived class.

When you refer to a derived class object using a pointer or a reference to the base class, you can call a virtual function for that object and execute the derived class’s definition of the function, otherwise, if you do not mark the function as the virtual function, then the base class definition of that function will be called as the pointer is of the base class type.

Functions are declared as virtual with the help of a virtual keyword in the base class and then there is no need to use a virtual keyword in the derived class, as functions are automatically considered as virtual functions in the derived class if declared in the base class.

Virtual functions are mainly used to achieve run time polymorphism, it ensures that the correct function is called for an object, regardless of the type of reference (or a pointer) used for a function call, and the function call is resolved at run time.

There are some rules which we have to follow while creating virtual functions:

  • Virtual functions are always defined in the base class and their definition is overridden in a derived class. It is not mandatory for the derived class to override the definition, in that case, the base class version or the definition of the function will be called.
  • Virtual functions should always be accessed using a pointer or reference of base class type to achieve runtime polymorphism.
  • The function's name, parameters, and return type of virtual functions should be the same for both the base class and the derived class.
  • Virtual functions cannot be static.
  • A virtual function can be a friend function of another class.

Let's understand virtual function with the help of an example:

The output of the above code would be:

In the code above, since the fun1() function is declared with a virtual keyword so it will be called at runtime (output is the fun1 derived class as the pointer is pointing to the object of the derived class) and fun2() is a non-virtual simple function, so it will be called during the compile-time (output is fun2 base class as the pointer is of base type).

All the types of polymorphism in c++, allows you to define one interface and have multiple implementations.

Pure Virtual Function

A pure virtual function is a virtual function for which we need not write any function defined in the base class, only we have to declare it. It is declared by assigning 0 in the declaration and using the virtual keyword.

or, we can also declare it using the syntax:

It is the function that must be overridden in a derived class and need not be defined in the base class.

The advantage of pure virtual function in C++ can be understood with the help of an example, let's say you have a base class Animal, having a member function as sound_produced_by_animal(). We can't provide the implementation of this member function in the base class, but we know every derived class must have the implementation of the sound_produced_by_animal() function. Similarly, an Animal class doesn’t have an implementation of the move() function, but all animals must know how to move, so we can provide its definition in the derived classes.

Such a class is called the abstract class as the implementation of all functions cannot be provided in a base class because we don’t know the implementation.

So, a pure virtual function (or abstract function) in C++ is a virtual function for which we can have an implementation, but we must override that function in the derived class, otherwise, the derived class will also become an abstract class.

Let's understand pure virtual function with the help of an example:

The output of the above code is:

Difference between Run-time and Compile-time Polymorphism

Compile Time PolymorphismRun time Polymorphism
In compile-time polymorphism, a function is called at the compile time.In run-time polymorphism, a function is called at the run time or the execution time.
It is also known as early binding or static binding.It is also known as late binding or dynamic binding.
It is achieved using function overloading and operator overloading.It is achieved using function overriding and virtual functions.
It is less flexible as all things execute at compile time.It is more flexible as all things execute at run time.
Inheritance is not involved in compile-time polymorphism.Inheritance is involved in rum time polymorphism.
In compile-time polymorphism, we know the function which needs to be executed at the early stage, so it provides fast execution.In run-time polymorphism, we know the function which needs to be executed at the later stage, so it provides slow execution as compared to compile-time polymorphism.
In compile-time polymorphism, the call is resolved by the compiler.In run time polymorphism, the call is not resolved by the compiler.

A Real-time Example of Polymorphism in C++

Let's see a real-life example of polymorphism: A person may have a variety of characteristics at the same time, suppose at the same time, a girl is a daughter, wife, mother, employee, sister, cousin, student, and friend. As a result, the same person behaves differently in different contexts and scenarios. Here, this girl represents the object, and her relationships with other persons display the ability of this object to be represented in many forms with totally different characteristics.

example-of-polymorphism

Let's take another example to understand the concept of polymorphism:

In shopping malls, we behave as a customer, On the bus, we behave like a passenger. In school, we behave like a student. At home, we behave like a son/daughter to our parents.

So, the same person exhibits different behavior in different situations, and this is why the word "Polymorphism" means multiple forms.

Conclusion

  • Polymorphism is defined as the process of using a function or an operator for more than one purpose. It is one of the main pillars of object-oriented programming in C++
  • Different types of polymorphism in c++ includes: compile time and run time polymorphism. In compile-time polymorphism, a function is called at the compile-time, and in run-time polymorphism, a function is called at the execution time.
  • Compile-time polymorphism is accomplished using function overloading and operator overloading, and run-time polymorphism is accomplished using virtual functions and function overriding.
  • Function overloading is defined as using the same function for different purposes just by changing the function signature.
  • Operator overloading is defined as the process of assigning additional tasks to operators without altering the actual meaning of the operation.
  • Function overriding means providing a new definition to the base class function in the derived class.
  • A virtual function is a base class member function, which is re-defined by a derived class, it is declared by using the virtual keyword.
  • A pure virtual function is a virtual function for which we need not write any function defined in the base class, only we have to declare it.