Virtual Functions in C++

Virtual Functions in C++

A virtual function is a member function of the base i.e. parent class which is overrided by function with the same name in the child class. We use virtual function to achieve Late Binding.

The definition may get you confused, so let us understand really how it works.

  • Defined in the base class
  • Used to perform Runtime polymorphism

Virtual functions are defined in base class as –

virtual void functionName(){

// some code

}
Virtual Functions in C++

How Virtual Functions work?

Now, lets try to understand why we need specifically a virtual functions –

Pre-Requisite 

First we need to work on the basics, so let us understand the requisite with a code

Consider we have parent vehicle class and child classes car and bike

#include <iostream>
using namespace std;

class Vehicle
{
public:
void start()
{
cout << "Vehicle started\n";
}
};

class Car : public Vehicle
{
public:
void start()
{
cout << "Car Started.\n";
}
};

class Bike : public Vehicle
{
public:
void start()
{
cout << "Bike Started.\n";
}
};

int main()
{
Vehicle vehicle_obj;
Car car_obj;
Bike bike_obj;

vehicle_obj.start();
car_obj.start();
bike_obj.start();
return 0;
}

Output:

Vehicle Started

Car Started.

Bike Started​

Now, the function start() is redeclared in the child classes and are also inheriting the one from parent class. The child objects call their own functions as the object calling those functions are of child classes. Thus they have overridden, the parent class method to their own, this is called function overriding and is a runtime event.

Imagine if we comment out the start declaration for bike class as –

class Bike : public Vehicle
{
public:
//commenting out below code
/*void start()
{
cout << "Bike Started.\n";
}*/
};

Output –

Output:

Vehicle Started

Car Started.

Vehicle Started​

Now, since, bike class doesn’t have its declaration of start() function it calls the parent class function that is has inherited. Note this.

Why it is Virtual Functions are needed

In most codes pointer references are used, let us use pointers.

  • Create pointer reference to the parent class
  • Create a child class object
  • assign address to base child class object

Something like this –

Parent *parent_object;

Child child_object;

parent_object = &child_object;
#include <iostream>
using namespace std;

class Vehicle
{
public:
void start()
{
cout << "Vehicle started\n";
}
};

class Car : public Vehicle
{
public:
void start()
{
cout << "Car Started.\n";
}
};

class Bike : public Vehicle
{
public:
void start()
{
cout << "Bike Started.\n";
}
};

int main()
{
Vehicle *vehicle_obj;
Bike bike_obj;
vehicle_obj = &bike_obj;

//with pointers we use -> instead of .
vehicle_obj->start();

return 0;
}

Now, one would expect Bike started to be printed, as the address location is eventually of the child class right? However, this doesn’t happen. Vehicle started is printed infact. This means that the reference is made to the parent function.

Now, this happens because of how C++ was written, in this case early binding happens, and the default function is set by the compiler at the compile time itself. This is also popularly known as static call effective static resolution.

Now, to solve this problem virtual functions come into the picture.

How Virtual Functions solve this problem?

By adding virtual keyword before the parent class definition of the function we can solve the problem of early binding and at run time the call ignores parent class function and calls child class function instead, in this way Run time polymorphism is achieved with the help of virtual functions. Let’s look at the code below –

#include <iostream>
using namespace std;

class Vehicle
{
public:
void start()
{
cout << "Vehicle started\n";
}
};

class Car : public Vehicle
{
public:
void start()
{
cout << "Car Started.\n";
}
};

class Bike : public Vehicle
{
public:
void start()
{
cout << "Bike Started.\n";
}
};

int main()
{
Vehicle *vehicle_obj;
Bike bike_obj;
vehicle_obj = &bike_obj;

//with pointers we use -> instead of .
vehicle_obj->start();

return 0;
}

Ouput –

Bike started.