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]

🧠 Test Your Knowledge

What keyword is used to declare a pure virtual function?