Virtual Functions
Dynamic polymorphism in C++
🔄 What are Virtual Functions?
Virtual functions enable runtime polymorphism in C++. They allow derived classes to override base class methods, with the correct function called based on the actual object type, not pointer type.
// Basic virtual function example
class Animal {
public:
virtual void makeSound() {
cout << "Some generic animal sound" << endl;
}
};
Key Virtual Function Concepts
Runtime Binding
Function called is determined at runtime
virtual void display() = 0;
Override
Derived classes can override virtual functions
void display() override {}
Pure Virtual
Abstract functions that must be implemented
virtual void func() = 0;
Virtual Destructor
Ensures proper cleanup in inheritance
virtual ~Base() {}
🔹 Basic Virtual Function Example
Here's how virtual functions work with inheritance:
#include <iostream>
using namespace std;
class Shape {
public:
virtual void draw() {
cout << "Drawing a generic shape" << endl;
}
virtual ~Shape() {} // Virtual destructor
};
class Circle : public Shape {
public:
void draw() override {
cout << "Drawing a circle" << endl;
}
};
class Rectangle : public Shape {
public:
void draw() override {
cout << "Drawing a rectangle" << endl;
}
};
int main() {
Shape* shapes[] = {new Circle(), new Rectangle()};
for (int i = 0; i < 2; i++) {
shapes[i]->draw(); // Calls correct derived function
delete shapes[i];
}
return 0;
}
Output:
Drawing a circle
Drawing a rectangle
🔹 Pure Virtual Functions (Abstract Classes)
Pure virtual functions create abstract classes that cannot be instantiated:
class Vehicle {
public:
// Pure virtual function
virtual void startEngine() = 0;
virtual void stopEngine() = 0;
// Regular virtual function
virtual void honk() {
cout << "Beep beep!" << endl;
}
};
class Car : public Vehicle {
public:
void startEngine() override {
cout << "Car engine started" << endl;
}
void stopEngine() override {
cout << "Car engine stopped" << endl;
}
};
// Vehicle v; // Error! Cannot instantiate abstract class
Car myCar; // OK! Car implements all pure virtual functions
🔹 Virtual Function Table (VTable)
Understanding how virtual functions work internally:
How VTable Works:
- VTable: Each class with virtual functions has a table of function pointers
- VPtr: Each object has a pointer to its class's VTable
- Runtime Lookup: Function calls are resolved through VTable lookup
- Performance: Small overhead due to indirection
class Base {
public:
virtual void func1() { cout << "Base::func1" << endl; }
virtual void func2() { cout << "Base::func2" << endl; }
};
class Derived : public Base {
public:
void func1() override { cout << "Derived::func1" << endl; }
// func2 inherited from Base
};
// VTable for Base: [Base::func1, Base::func2]
// VTable for Derived: [Derived::func1, Base::func2]