A virtual function is a member function in a base class that can be overridden in a derived class. It allows C++ to select the appropriate function implementation at runtime when the function is called through a base class pointer or reference.
A virtual function is declared using the virtual keyword
inside a base class.
class Animal {
public:
virtual void sound() {
std::cout <<
"Animal sound";
}
};
A derived class can provide its own implementation of
sound().
Virtual functions are useful when a base class pointer or reference should call the implementation belonging to the actual derived object.
They allow one common interface to work with different derived classes.
Animal* animal = &dog;
animal->sound();
If sound() is virtual, the appropriate overridden function
can be selected at runtime.
The basic syntax is:
class Base {
public:
virtual void functionName() {
// implementation
}
};
The derived class can override the function.
class Derived : public Base {
public:
void functionName() override {
// new implementation
}
};
#include <iostream>
class Animal {
public:
virtual void sound() {
std::cout <<
"Animal makes a sound";
}
};
class Dog : public Animal {
public:
void sound() override {
std::cout <<
"Dog barks";
}
};
int main() {
Dog dog;
dog.sound();
return 0;
}
Here, Dog overrides the virtual sound()
function.
When a derived class provides its own implementation of a virtual function from the base class, it is called function overriding.
class Animal {
public:
virtual void sound() {
std::cout <<
"Animal sound";
}
};
class Cat : public Animal {
public:
void sound() override {
std::cout <<
"Cat meows";
}
};
The override keyword indicates that a derived class
function is intended to override a virtual function from the base
class.
class Dog : public Animal {
public:
void sound() override {
std::cout <<
"Dog barks";
}
};
It helps the compiler detect mistakes in the function signature.
A base class pointer can point to a derived class object.
Dog dog;
Animal* animal = &dog;
animal->sound();
If sound() is virtual, the derived implementation is
called.
Virtual functions are commonly used to achieve runtime polymorphism.
class Animal {
public:
virtual void sound() {
std::cout <<
"Animal sound";
}
virtual ~Animal() = default;
};
class Dog : public Animal {
public:
void sound() override {
std::cout <<
"Dog barks";
}
};
int main() {
Dog dog;
Animal* animal = &dog;
animal->sound();
return 0;
}
The call is resolved according to the actual object.
Runtime polymorphism can also work through a base class reference.
Dog dog;
Animal& animal = dog;
animal.sound();
The virtual function mechanism selects the overridden
Dog::sound() implementation.
class Animal {
public:
virtual void sound() {
std::cout <<
"Animal sound";
}
virtual ~Animal() = default;
};
class Dog : public Animal {
public:
void sound() override {
std::cout <<
"Dog barks";
}
};
class Cat : public Animal {
public:
void sound() override {
std::cout <<
"Cat meows";
}
};
Different derived classes can provide different implementations of the same virtual function.
Dog dog;
Cat cat;
Animal* a1 = &dog;
Animal* a2 = &cat;
a1->sound();
a2->sound();
The same base-class interface produces different behavior for the different objects.
void makeSound(
Animal& animal
) {
animal.sound();
}
int main() {
Dog dog;
Cat cat;
makeSound(dog);
makeSound(cat);
return 0;
}
The function does not need separate versions for Dog and
Cat. It works through the common base interface.
| Feature | Normal Function | Virtual Function |
|---|---|---|
| Keyword | No virtual |
Uses virtual |
| Runtime Dispatch | Not provided through the virtual mechanism | Supported |
| Overriding | Can hide a base function | Can provide runtime overriding behavior |
| Common Use | Regular class behavior | Runtime polymorphism |
Virtual functions are especially useful in inheritance hierarchies.
class Vehicle {
public:
virtual void start() {
std::cout <<
"Vehicle starts";
}
virtual ~Vehicle() = default;
};
class Car : public Vehicle {
public:
void start() override {
std::cout <<
"Car starts";
}
};
The derived class can customize inherited behavior.
A pure virtual function is a virtual function declared with
= 0.
class Shape {
public:
virtual double area() = 0;
};
A class containing a pure virtual function is abstract.
class Shape {
public:
virtual void draw() = 0;
virtual ~Shape() = default;
};
class Circle : public Shape {
public:
void draw() override {
std::cout <<
"Drawing Circle";
}
};
The abstract class defines the required interface, while the derived class provides the implementation.
A polymorphic base class should commonly have a virtual destructor when objects may be deleted through a base pointer.
class Animal {
public:
virtual void sound() = 0;
virtual ~Animal() = default;
};
This supports the correct destruction sequence when deleting derived objects through base-class pointers.
class Base {
public:
virtual ~Base() {
std::cout <<
"Base destructor";
}
};
class Derived : public Base {
public:
~Derived() {
std::cout <<
"Derived destructor";
}
};
int main() {
Base* ptr = new Derived();
delete ptr;
return 0;
}
Because the base destructor is virtual, destruction can follow the derived-to-base sequence.
class Animal {
public:
virtual void eat(
std::string food
) {
std::cout <<
"Animal eats "
<< food;
}
virtual ~Animal() = default;
};
class Dog : public Animal {
public:
void eat(
std::string food
) override {
std::cout <<
"Dog eats "
<< food;
}
};
Virtual functions can have parameters like normal member functions.
class Shape {
public:
virtual double area() {
return 0;
}
virtual ~Shape() = default;
};
class Rectangle : public Shape {
private:
double length;
double width;
public:
Rectangle(
double l,
double w
)
: length(l),
width(w) {
}
double area() override {
return length * width;
}
};
A virtual function can return values just like other functions.
A derived class can explicitly call the base class version using the scope resolution operator.
class Animal {
public:
virtual void sound() {
std::cout <<
"Animal sound";
}
};
class Dog : public Animal {
public:
void sound() override {
Animal::sound();
std::cout <<
"Dog barks";
}
};
Animal::sound() explicitly calls the base implementation.
Many C++ implementations use an internal mechanism commonly described as a virtual table (vtable) and a related pointer to support virtual dispatch.
The exact implementation is compiler-dependent and is not something the C++ language requires programmers to manage directly.
Animal* animal = &dog;
animal->sound();
The language-level idea is that the virtual call selects the appropriate overridden function for the actual object.
Consider a base pointer pointing to a derived object:
Dog dog;
Animal* ptr = &dog;
The pointer type is Animal*, but the actual object is a
Dog.
For a virtual function call, the derived implementation can therefore be selected.
#include <iostream>
class Employee {
public:
virtual double salary() {
return 0;
}
virtual ~Employee() = default;
};
class Manager : public Employee {
public:
double salary() override {
return 60000;
}
};
class Developer : public Employee {
public:
double salary() override {
return 50000;
}
};
int main() {
Manager manager;
Developer developer;
Employee* e1 = &manager;
Employee* e2 = &developer;
std::cout <<
e1->salary()
<< std::endl;
std::cout <<
e2->salary();
return 0;
}
The same salary() interface can produce different results
for different employee types.
class Animal {
public:
virtual void sound() = 0;
virtual ~Animal() = default;
};
class Dog : public Animal {
public:
void sound() override {
std::cout <<
"Dog barks\n";
}
};
class Cat : public Animal {
public:
void sound() override {
std::cout <<
"Cat meows\n";
}
};
int main() {
Dog dog;
Cat cat;
Animal* animals[] = {
&dog,
&cat
};
for(Animal* animal : animals) {
animal->sound();
}
return 0;
}
A collection of base pointers can work with different derived object types through the same virtual interface.
virtual keyword when runtime polymorphism is intended.override in derived classes.virtual when runtime polymorphism is required.override in derived classes.std::unique_ptr when dynamic ownership is needed.sound().start().pay().area() or draw().send().| Concept | Meaning |
|---|---|
| Virtual Function | A base-class function that supports runtime dispatch when called through a suitable base pointer or reference. |
| Override | A derived-class implementation of a virtual base-class function. |
| Runtime Polymorphism | Calling behavior based on the actual object at runtime. |
| Pure Virtual Function | A virtual function declared using = 0. |
| Abstract Class | A class that contains at least one pure virtual function. |
| Virtual Destructor | A destructor that supports appropriate polymorphic destruction through a base pointer. |
class Animal {
public:
virtual void sound() = 0;
virtual ~Animal() = default;
};
class Dog : public Animal {
public:
void sound() override {
std::cout <<
"Dog barks";
}
};
int main() {
Dog dog;
Animal* animal = &dog;
animal->sound();
return 0;
}
This example demonstrates the core idea of virtual functions: a base-class interface can be used to call the appropriate derived implementation at runtime.
virtual keyword.override keyword helps verify overriding.= 0.Question: What is the main purpose of a virtual function in C++?