Along with function overloading and operator overloading, C++ also has other types of polymorphism called virtual function. In function overloading and operator overloading the selection of the function takes place at compile time while selection of the function for the virtual functions takes place at runtime. The classes that have virtual function are called polymorphic classes. The objects of the polymorphic class when accessed by pointers changes at runtime and respond differently for the same message (function call). Such mechanism postpones the binding of a function call to the member function declared as virtual for runtime. For overloaded function, the decision for selecting the function for invoking is done at compile time by matching the argument type, number or both. For function overloading compiler is able to resolve function call at compile time so it is called compile time polymorphism. This form of resolving a function call at compile time is called early binding or static binding. Similar to function overloading, operator overloading is also called the compile time polymorphism of C++. Now let us see a condition where a derived class has overridden a function of the base as
class shape{private:
int type;
public:
void draw();
};
class circle:public shape{
private:
float radius;
public:
void draw();
};
In this situation we can access the base class draw() using scope resolution operator from the derived class object and the derived class draw() can be called directly from the derived class object.
circle cir;
circle cir;cir.shape::draw(); //calls the base class draw()
cir.draw(); //calls the derived class draw()
In both of the cases the call to the specific function is indicated by the code itself. But when we use pointer of the derived class to select the appropriate draw() function from base class or derived class then appropriate function can be called at runtime. When the pointers to objects are involved in calling function the selection of the function is done at the runtime because the address information is known only at runtime. In C++ the selection of appropriate function can be done through object pointer by means of virtual function. This is called runtime polymorphism. Since the function to be called is selected later after the compilation during runtime, this process is called late binding or dynamic binding. If we create different derived classes like circle, triangle, and rectangle from the base class shape and if all of them override the function draw() we could have created the array of pointer to shape as:
If we assign the address of derived class object of base class shape to this array of pointer to shape we can call the draw() function of the specific object through this array of pointer as:
for(int i=0; i < 3; i++)
sptr[i]->draw();
The interesting point with this statement is that completely different functions are executed by the same function call if we make the base class member function draw() as virtual. An example program with source code which illustrates the concept of virtual function is given below:
#include<iostream>
#include<cstdlib>
using namespace std;
class test{
public:
int data;
test(){
cout<<"\nConstructor test() is called "<<endl;
data=55;
}
~test(){
cout<<"\nDestructor ~test() is called"<<endl;
}
void show(){
cout<<"\ndata is "<<data<<endl;
}
};
int main(){
test *ptr;
test tobj; //constructor is invoked here
//store the address of statically created object tobj
ptr=&tobj;
cout<<"\nAccessing object through tobj.show()..";
tobj.show();
cout<<"\nAccessing object through ptr->show()..";
ptr->show();
return 0;
}