The following example illustrates this concept of why virtual function is necessary.
1: #include<iostream>
2:
3: using namespace std;
4: class Animal{
5: public:
6: void display(){cout<<"\nFrom Base class Animal";}
7: };
8:
9: class Cow:public Animal{
10: public:
11: void display(){cout<<"\n From Derived class Cow";}
12: };
13:
14: class Dog:public Animal{
15: public:
16: void display(){ cout<<"\nFrom Derived class Dog";}
17: };
18:
19: int main(){
20: Animal *panm; //pointer to base class
21: Animal anm;
22: Cow cw;
23: Dog dg;
24:
25: panm = &anm;
26: panm->display();
27:
28: panm=&cw;
29: panm->display();
30:
31: panm=&dg;
32: panm->display();
33: return 0;
34: }
When the above program is executed, it will produce the output as:
From Base class Animal
From Base class Animal
From Base class Animal
In this program we have created pointer to the base class Animal as:
Animal *panm;
First this pointer to base class Animal is assigned with the address of the object of base class animal as in line 25. When a function display() is called through this pointer to object panm as line 26, we can easily guess that it will call the function of the base class Animal to produce the output as above as “From Base class Animal”.
In C++, the base class pointers are type compatible with derived class pointers. So we can assign the address of the objects of derived class Cow and Dog to the pointer variable panm as line 28. With this statement compiler does not see any problem, so it will compile normally without generating error message. Now when the function display() is called through this pointer to object of class Animal panm as line 29, the output will be unexpected. In this case instead of calling the display() of the derived class Cow the function display() of the base class Animal is called. Similar to the case when we assign the address of object of other derive class Dog to this pointer to the base class object panm, the output will still be same.
Let’s see what is happening in this case. In this case during the compilation, it always selects the base class function as it is a pointer to the base class object. The compiler is unknown about the address, which is known at runtime and chooses the member function that matches the type of the pointer. So when the program is executed the base class function is called every time.
In C++, there is provision for selecting the particular function as according to the address of the object the pointer holds. So when the pointer to the base class points to the base class objects, it will invoke the base class function and when it points to the derive class object it invokes the derive class function. And this is done by making a base class function virtual. Which is done in following modified code below:
1: #include<iostream>
2:
3: using namespace std;
4: class Animal{
5: public:
6: virtual void display(){cout<<"\nFrom Base class Animal";}
7: };
8:
9: class Cow:public Animal{
10: public:
11: void display(){cout<<"\nFrom Derived class Cow";}
12: };
13:
14: class Dog:public Animal{
15: public:
16: void display(){ cout<<"\nFrom Derived class Dog";}
17: };
18:
19: int main(){
20: Animal *panm; //pointer to base class
21: Animal anm;
22: Cow cw;
23: Dog dg;
24:
25: panm = &anm;
26: panm->display();
27:
28: panm=&cw;
29: panm->display();
30:
31: panm=&dg;
32: panm->display();
33: return 0;
The output of the code is
From Base class Animal
From Derived class Cow
From Derived class Dog