0
0
CppHow-ToIntermediate · 4 min read

How Virtual Function Works Internally in C++ Explained

In C++, a virtual function works internally using a vtable (virtual table) and a vptr (virtual pointer). Each class with virtual functions has a vtable storing addresses of these functions, and each object has a vptr pointing to its class's vtable, enabling dynamic dispatch at runtime.
📐

Syntax

A virtual function is declared by adding the virtual keyword before the function declaration inside a class. This tells the compiler to use dynamic dispatch for this function.

  • virtual: Marks the function as virtual.
  • return_type: The type of value the function returns.
  • function_name(): The function's name and parameters.

Example syntax:

cpp
class Base {
public:
    virtual void show();
};
💻

Example

This example shows how virtual functions enable calling the correct function version based on the actual object type, not the pointer type.

cpp
#include <iostream>
using namespace std;

class Base {
public:
    virtual void show() {
        cout << "Base show() called" << endl;
    }
};

class Derived : public Base {
public:
    void show() override {
        cout << "Derived show() called" << endl;
    }
};

int main() {
    Base* ptr;
    Derived d;
    ptr = &d;
    ptr->show(); // Calls Derived::show() because show() is virtual
    return 0;
}
Output
Derived show() called
⚠️

Common Pitfalls

Common mistakes with virtual functions include:

  • Forgetting to declare the base class function as virtual, which disables dynamic dispatch.
  • Calling virtual functions inside constructors or destructors, which uses the current class's version, not derived overrides.
  • Not using override keyword in derived classes, which helps catch mistakes.
cpp
#include <iostream>
using namespace std;

class Base {
public:
    void show() { // Missing virtual keyword
        cout << "Base show()" << endl;
    }
};

class Derived : public Base {
public:
    void show() {
        cout << "Derived show()" << endl;
    }
};

// Usage:
// Base* ptr = new Derived();
// ptr->show(); // Calls Base::show(), not Derived::show() because show() is not virtual
📊

Quick Reference

How virtual functions work internally:

  • Each class with virtual functions has a vtable storing pointers to those functions.
  • Each object has a hidden vptr pointing to its class's vtable.
  • When calling a virtual function, the program uses the vptr to find the right function address in the vtable and calls it.
  • This enables runtime polymorphism where the function called depends on the actual object type.

Key Takeaways

Virtual functions use a vtable and vptr to enable dynamic dispatch at runtime.
Declare functions as virtual in the base class to enable polymorphism.
Calling virtual functions in constructors/destructors calls the current class version, not derived overrides.
Use the override keyword in derived classes to avoid mistakes.
Without virtual, function calls are resolved at compile time, not runtime.