Mastering C++ Virtual Functions: Concepts, Examples, and the Override Keyword
C++ Virtual Functions
This tutorial explains C++ virtual functions, their purpose, and practical usage illustrated with code examples.
A virtual function is a base‑class member that we expect derived classes to override. Declaring a function virtual ensures that the most derived implementation is invoked, even when accessed through a base‑class pointer or reference.
When a base class contains a non‑virtual member, calling that member via a base pointer will always execute the base version, regardless of the actual object type. Consider the following:
class Base {
public:
void print() {
// base implementation
}
};
class Derived : public Base {
public:
void print() {
// derived implementation
}
};
In the program below, a Base* points to a Derived instance, yet print() resolves to the base version:
int main() {
Derived derived1;
Base* base1 = &derived1;
base1->print(); // calls Base::print()
return 0;
}
To achieve polymorphic behavior, declare the function as virtual in the base class:
class Base {
public:
virtual void print() {
// base implementation
}
};
Virtual functions are central to C++ polymorphism. For a deeper dive, see our C++ Polymorphism guide.
Example 1: Basic Virtual Function Usage
#include <iostream>
using namespace std;
class Base {
public:
virtual void print() {
cout << "Base Function" << endl;
}
};
class Derived : public Base {
public:
void print() override {
cout << "Derived Function" << endl;
}
};
int main() {
Derived derived1;
Base* base1 = &derived1;
base1->print(); // prints Derived Function
return 0;
}
Output
Derived Function
Because Base::print is virtual, the call dispatches to Derived::print even through a base pointer.

The C++ Override Identifier
Since C++11, the override keyword helps prevent accidental mis‑overriding by forcing the compiler to verify that a function truly overrides a virtual base member.
Example:
class Base {
public:
virtual void print() {
// base implementation
}
};
class Derived : public Base {
public:
void print() override {
// derived implementation
}
};
If you define the overriding function outside the class, use:
class Derived : public Base {
public:
void print() override; // declaration
};
void Derived::print() {
// implementation
}
Using override Safely
Without override, a typo or signature mismatch silently results in a new function rather than an override, leading to subtle bugs. The compiler will then emit an error, making the issue immediately visible. Common pitfalls include:
- Mismatched names: e.g.,
pint()instead ofprint() - Different return types: e.g., returning
intinstead ofvoid - Parameter mismatch: differing parameter lists
- Missing virtual in base: the base function is not virtual at all
Practical Use of Virtual Functions
Consider an Animal base class with derived Dog and Cat classes. Each class holds a type member initialized by its constructor.
class Animal {
private:
string type;
public:
Animal() : type("Animal") {}
virtual string getType() const { return type; }
};
class Dog : public Animal {
private:
string type;
public:
Dog() : type("Dog") {}
string getType() const override { return type; }
};
class Cat : public Animal {
private:
string type;
public:
Cat() : type("Cat") {}
string getType() const override { return type; }
};
With getType() virtual, a single helper can print any animal:
void print(Animal* ani) {
cout << "Animal: " << ani->getType() << endl;
}
Usage in main():
int main() {
Animal* animal1 = new Animal();
Animal* dog1 = new Dog();
Animal* cat1 = new Cat();
print(animal1);
print(dog1);
print(cat1);
delete animal1;
delete dog1;
delete cat1;
return 0;
}
Output
Animal: Animal Animal: Dog Animal: Cat
By making getType() virtual, we avoid duplicating print() logic in each derived class and ensure that the correct type is accessed.
C Language
- Mastering C++ Functions: From Basics to Advanced Usage
- C++ Function Overloading: A Practical Guide
- Master C++ Inheritance: Build Powerful Classes with Reusable Code
- C++ Function Overriding Explained – Practical Examples & Best Practices
- C++ Friend Functions and Friend Classes: Mastering Access Control
- Mastering C++ Class Templates: A Practical Guide
- Mastering C Functions: User-Defined and Standard Library Basics
- C++ Functions Explained with Practical Code Examples
- Mastering C Functions: Structure, Declaration, and Best Practices
- Understanding Polymorphism in C++: A Practical Guide