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)
In a case when a function is declared in both the parent class(Base Class) and child class(Derived Class).
Example
#include
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.
What is this called
This is behaviour shown by the child class object is called function overriding and this happens at run time. The child object has overridden the function definition of parent class and chose to exhibit its own properties.
What if?
Now, what if the child class didn't have its own function declaration, in this case, it would have gone ahead with the inherited parent class definition of the print() function.
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
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 –
Note :
In below example, compile time polymorphism happens. We will force runtime polymorphism later in 2nd example below when we force it using virtual functions
Example
#include
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
What happenned above (Static Resolution)
Now, this happens because of how C++ was written by its writer. Now, while run time polymorphism may exhibit dynamic (or late) binding.
But, this instance is a classic example of early binding as the print() function is set during the compilation of the program. The definition of C++ is written, forces this static call and is also called as static resolution.
Thus, the above is an example of Compile time polymorphism. Also known as early binding.
How to force into Runtime Polymorphism (Virtual Functions)
The issue caused by static resolution is solved by using virtual function that turns the early binding into late binding i.e. compile time process to runtime process.
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).
Example
#include
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
What exactly happenned
Using the virtual keyword guarentees that the base(parent) class function is overridden and dervided(child) class function is implemented
This is called as late binding at runtime, thus runtime polymorphism is implemented. We solved the problem of static resolution which had earlier forced early binding(Compile time polymorphism)