Why do we need virtual functions in C++?

Let’s look at the class definition below:


class Base {
public:
void welcome_message() {cout << "Welcome to Base class" << endl;}
};

class Derived : public Base {
public:
void welcome_message() {cout << "Welcome to Derived class" << endl;}
};

Lets assume we have to design a function which will take a pointer to the class object and print the welcome message by calling the class member function welcome_message(). Here is the function which can do the same for us:


void printMessage(class Base *ptr)
{
ptr->welcome_message();
}

Now, if we call the printMessage() with the Base class pointer it will print the message as below:


int main()
{
Base *bptr = new Base();
printMessage(bptr);

return 0;
}

print1.png

Now what about the Derived class, we would like to do the same with a Derived class pointer as well. Lets try in the same way as below:


int main()
{
Derived *dptr = new Derived();
printMessage(dptr);

return 0;
}

In the above program we have modified previously existing main() functionto create a Derived class object which is pointed by a Derived class type pointer dptr. Now, we pass the dptr pointer to printMessage() function and here is the output:

print1.png

As you can see the function printMessage() takes the dptr into a Base class type pointer ptr (look into the formal parameter in the function printMessage). Now, printMessage() doesn’t have any idea what is the object type and uses the pointer type to determine the object type which is Base class. Hence, it ends up calling the Base class version of the member function welcome_message(). This is certainly we didn’t want to do, what we wanted is that printMessage() would call the Derived class version of the welcome_message() but that didn’t happen. One solution to this problem is defining yet another printMessage() function with Derived class type pointer in the formal argument list, in other words overloading the printMessage() function as below:


void printMessage(class Derived *ptr)
{
ptr->welcome_message();
}

Now, if we execute the program again it will give us the desired output as below:

print1.png

However, this is not an optimized solution to the problem. We need common function/interfaces which can work for us both with a Base type object as well as with a Derived class object. And virtual function is what helps us achieving this. Lets see the redefined Base class definition as below which uses virtual keyword in front of the welcome_message() member function as below:


class Base {
public:
virtual void welcome_message() {cout << "Welcome to Base class" << endl;}
};

class Derived : public Base {
public:
void welcome_message() {cout << "Welcome to Derived class" << endl;}
};

Now, lets modify our main() function again to check if it has solved our problem yet:

int main()
{
Base *bptr = new Derived();

printMessage(bptr);

bptr = new Base();

printMessage(bptr);

return 0;
}

Execute the code and the below output will be generated:

print1.png

As you can see the same pointer bptr first, points to a Derived class object, printMessage() is called with bptr and it prints the message “Welcome to Derived class”. Then the same bptr points to a Base class object and the printMessage() function prints the message “Welcome to Base class”.

So by using the virtual function mechanism we have been able to create a generic function called printMessage() which works for both the Base class object type as well as the Derived class object type.  These type of functions are called interfaces in c++.

Here is the full listing of the source code:


#include 

using namespace std;

class Base {
public:
virtual void welcome_message() {cout << "Welcome to Base class" << endl;}
};

class Derived : public Base {
public:
void welcome_message() {cout << "Welcome to Derived class" <welcome_message();
}

int main()
{
Base *bptr = new Derived();

printMessage(bptr);

bptr = new Base();

printMessage(bptr);

return 0;
}

Note: 

There is an inherent issue withe the above code and that is memory leak. As the bptr pointer has been overridden there is noway the Derived class object can be free. To get rid of this should call a delete() on bptr before overriding it with the Base class object as below:


int main()
{
Base *bptr = new Derived();

printMessage(bptr);

delete(bptr);

bptr = new Base();

printMessage(bptr);

return 0;
}

 

 

 

 

 

 

 

 

 

 

 

 

 

One thought on “Why do we need virtual functions in C++?

  1. […] However, one question which might come into your mind as why would one should use a Base class pointer to point to a Derived class object at all. If you have noticed if we use a  Derived class pointer to point to a Derived class object which is described in Section 3, there is absolutely no problem. The problem starts when we use a Base class pointer pointing to a Derived class object, and use that pointer to call a function defined in both class and the Derived class. For why we care to use the Base class pointer please refer to the post Why we need virtual function? […]

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s