In object-oriented programming, virtual functions are object methods that are inheritable and overridable. This allows derived classes to access the member data/functions of a base object, if they aren’t re-implemented in the derived class. Another key mechanism is the overridability, where we can re-implement our own version of the virtual function in the derived class.

One use-case is if we have assign a derived class object to a base class pointer, in a process called upcasting.

Base* basePtr = new Derived();
Base& baseRef = derivedObj;

This base class can only directly access members declared in the base class. However, if they’re virtual functions, we can correctly call the derived class’ implementation instead of the base class.

class Polygon {
	protected:
		int width, height;
	public:
		void set(int w, int h) {
			width = w;
			height = h;
		}
		virtual int area() { return 0; }
}
 
p1->area(); // invoke the area function of what p1 is pointing to

Non-virtual functions are invoked depending on the type of pointer, which is known at compile-time. Virtual functions are invoked depending on the type the pointer points to, known at run-time (dynamic dispatch).

A class that inherits a virtual function is called a polymorphic class.

Defining

When we define virtual functions, our function signature looks like:

virtual void draw();

Objects of the base class may sometimes never be intended to be instantiated and only serve to derive other classes. We can enforce pure virtual methods that don’t have a definition by default, so any derived class should re-define.

virtual double area() = 0;

A class with one or more pure virtual functions is called an abstract class, because objects of these classes cannot be instantiated. They’re also sometimes called interfaces, because they force derived classes to define the virtual function they inherit.

In a derived class, we can also define a virtual function (or class) implementation that can’t be overridden in further derived classes:

void draw() override final;

We can disable virtual function dispatch (i.e., keep a function local to a class) with the static keyword:

static void draw(); // only callable from base, if from derived need new implementation

We can also set a default implementation of a virtual function:

virtual void draw() = default;

Overriding

We can override a function by defining a function with the same function signature. We don’t need to use virtual again, since it’s inherited from the base class, but we can if we want. To specify that we’re overriding a virtual function, we should use the override keyword.

void draw() override;

This keyword ensures that the compiler knows we’re strictly overriding a virtual function. If the virtual function in the base class doesn’t exist, then it’ll cause a compile-time error.

This is useful if we remove the virtual function later down the line in the base class. It’s an extra step for us to ensure our code’s intentions don’t break.

If we don’t want to use a virtual function, we can delete it and prevent its use:

void draw() = delete;