When to Use Virtual Functions in C++?

In the previous article, we have discussed about C++ Vector : Print all elements – (6 Ways). Let us learn how to Use Virtual Functions in C++ Program.

When to Use Virtual Functions?

When it comes to derive a class to override a member function of base class , then member function in base class is made virtual. So, when the derived class object is used using base class pointer or reference to call the overridden member function then in this condition the derived class is called . By making the function virtual signals compiler to not link the function call with actual function address at compile time and leave it for run time.

Virtual member function example program:

Let’s look into an example. A base class MsgConverter has a member function convert( ) that will convert the message into a desired format. And then there is a class called MsgSender which utilises the MsgConverter class and then sends the message.

#include <bits/stdc++.h>
class MsgConverter
{
public:
    std::string convert(std::string msg)
    {
        msg = "[START]" + msg + "[END]";
        return msg;
    }
};

class MsgSender
{
    MsgConverter *mMsgConverterPtr;

public:
    MsgSender() : mMsgConverterPtr(NULL) {}
    void sendMessage(std::string msg)
    {
        if (mMsgConverterPtr)
            msg = mMsgConverterPtr->convert(msg);
        std::cout << "Sent :: " << msg << std::endl;
    }
    void setMsgConverterPtr(MsgConverter *msgConverterPtr)
    {
        mMsgConverterPtr = msgConverterPtr;
    }
};

int main(int argc, char const *argv[])
{
    MsgSender msgSenderObj;
    MsgConverter *msgConverterPtr = new MsgConverter();
    msgSenderObj.setMsgConverterPtr(msgConverterPtr);
    msgSenderObj.sendMessage("Hey user!!");
    delete msgConverterPtr;
    return 0;
}
Output :

Sent :: [START]Hey user!![END]

The program is fine for now, but in case there is a new requirement where the message is required in some other format, we are not allowed to change either of the classes.

In such places we will create a new class containing the function and override it.

#include <bits/stdc++.h>
class MsgConverter
{
public:
    std::string convert(std::string msg)
    {
        msg = "[Begin]" + msg + "[Finish]";
        return msg;
    }
};

class MsgSender
{
    MsgConverter *mMsgConverterPtr;

public:
    MsgSender() : mMsgConverterPtr(NULL) {}
    void sendMessage(std::string msg)
    {
        if (mMsgConverterPtr)
            msg = mMsgConverterPtr->convert(msg);
        std::cout << "Sent :: " << msg << std::endl;
    }
    void setMsgConverterPtr(MsgConverter *msgConverterPtr)
    {
        mMsgConverterPtr = msgConverterPtr;
    }
};
class NewMsgConverter : public MsgConverter
{
public:
    std::string convert(std::string msg)
    {
        msg = "<Begin> " + msg + " <Finish>";
        return msg;
    }
};
int main(int argc, char const *argv[])
{
    MsgSender msgSenderObj;
    MsgConverter *newMsgConverterPtr = new NewMsgConverter();
    msgSenderObj.setMsgConverterPtr(newMsgConverterPtr);
    msgSenderObj.sendMessage("Hey user!!");
    delete newMsgConverterPtr;
    return 0;
}

Output :

Sent :: [Begin]Hey user!![Finish]

We did override the class however we could not get the desired output. That is because the base class function is being called again instead of the NewMsgConverter( ) class. The reason behind this is the convert( ) is being called by using MsgConverter pointer and not the function is not declared as virtual inside our base class.

How to make MessageSender call actual Derived class i.e. NewMessageConverter’s member function convert() instead of base class’s function?

Now to make convert function virtual inside the base class we have to add virtual before the function name.

#include <bits/stdc++.h>
class MsgConverter
{
public:
    virtual std::string convert(std::string msg)
    {
        msg = "[Begin]" + msg + "[Finish]";
        return msg;
    }
};

class MsgSender
{
    MsgConverter *mMsgConverterPtr;

public:
    MsgSender() : mMsgConverterPtr(NULL) {}
    void sendMessage(std::string msg)
    {
        if (mMsgConverterPtr)
            msg = mMsgConverterPtr->convert(msg);
        std::cout << "Sent :: " << msg << std::endl;
    }
    void setMsgConverterPtr(MsgConverter *msgConverterPtr)
    {
        mMsgConverterPtr = msgConverterPtr;
    }
};
class NewMsgConverter : public MsgConverter
{
public:
    std::string convert(std::string msg)
    {
        msg = "<Begin> " + msg + " <Finish>";
        return msg;
    }
};
int main(int argc, char const *argv[])
{
    MsgSender msgSenderObj;
    MsgConverter *newMsgConverterPtr = new NewMsgConverter();
    msgSenderObj.setMsgConverterPtr(newMsgConverterPtr);
    msgSenderObj.sendMessage("Hey user!!");
    delete newMsgConverterPtr;
    return 0;
}
Output :

Sent :: <Begin> Hey user!! <Finish>