C++ Polymorphism and Virtual Function
The concept of polymorphism enables one entity to be used as general category for different types of actions. The specific action is determined by the exact nature of the situation. This concept can be explained as “one interface, multiple methods”.
Polymorphism in C++ can be broadly categorized into two types —
- Compile-time Polymorphism
- Runtime Polymorphism
Compile-time Polymorphism – It is called early binding or static binding. Examples include function overloading and operator overloading (discussed earlier).
Runtime Polymorphism – It is called late binding or dynamic binding. Example includes function overriding (discussed earlier).
A virtual function is a C++ member function which is declared within a base class and is overridden by a derived class. When we refer to a derived class object using a pointer (or reference) to the base class, we can call a virtual function for that object and execute the derived class’s version of the function. Some properties of the virtual functions are mentioned below –
- Virtual functions assure that the correct function is to be invoked (i.e. called) for an object, irrespective of the type of pointer (or reference) used for the function call.
- They are primarily used to achieve runtime polymorphism.
- Functions are declared with the virtual keyword in the base class.
- The function call is resolved at runtime.
Rules for Virtual Functions
- Virtual functions in C++ can’t be static and also can’t be a friend function of another class.
- They should be accessed using a pointer of the base class to achieve runtime polymorphism.
- The prototype of virtual functions should be same in the base class as well as in derived class.
- Virtual functions are always defined in the base class and overridden in the derived class.
- A C++ class may have virtual destructor but it can’t have a virtual constructor.
To illustrate what happens when we don’t mark an overridden function as virtual, let us take a programming example.
Overriding a non-virtual function
Try to understand the scenario here. Even though we have the base class pointer pointing to the object of the child class, the base class version of the function gets called always.
Let us consider the following example program (poly01.cpp) where a base class has been derived by other two classes −
#include <iostream>
using namespace std;
// Base class
class Student {
public:
void course() {
cout << "Student generic course() function" << endl;
}
};
// Derived class 1
class UGStudent : public Student {
public:
void course() {
cout << "UGStudent specific course() function" << endl;
}
};
// Derived class 2
class PGStudent : public Student {
public:
void course() {
cout << "PGStudent specific course() function" << endl;
}
};
int main() {
Student *obj;
obj = new UGStudent();
obj->course();
obj = new PGStudent();
obj->course();
return 0;
}
Output of the program is given below:
Student generic course() function
Student generic course() function
The program works as follows:
When we use base class’s pointer to hold derived class’s object, base class pointer or reference will always call the base class version of the function (provided it is non-virtual).
Overriding a virtual function
We can make the base class’s function virtual by using virtual keyword while declaring them. Use of virtual keyword will lead to late binding of that function.
Let us consider the following example program (poly02.cpp) where using virtual keyword with the base class’s function, late binding takes place and the derived version of function will be get called, because the base class pointer refers to the derived class object −
#include <iostream>
using namespace std;
// Base class
class Student {
public:
virtual void course() {
cout << "Student generic course() function" << endl;
}
};
// Derived class 1
class UGStudent : public Student {
public:
void course() {
cout << "UGStudent specific course() function" << endl;
}
};
// Derived class 2
class PGStudent : public Student {
public:
void course() {
cout << "PGStudent specific course() function" << endl;
}
};
int main() {
Student *obj;
obj = new UGStudent();
obj->course();
obj = new PGStudent();
obj->course();
return 0;
}
Output of the program is given below:
UGStudent specific course() function
PGStudent specific course() function
The program works as follows:
When we use base class’s pointer to hold derived class’s object, base class pointer or reference will call the derived class version of the function (provided the base class function is declared as virtual).
NOTE: Even if the derived class version of the function is declared as private, we will get the same output as above.