Pure Virtual Functions

Vtable and Virtual Functions

What is a vtable, and how is it related to virtual functions?

Abstract art representing computer programming

A vtable, or virtual table, is a mechanism used by C++ to support dynamic polymorphism through virtual functions.

It is essentially a table of function pointers, with each entry pointing to the most derived implementation of a virtual function that can be called on a given object.

How Vtables Work

When a class declares or inherits virtual functions, the compiler generates a vtable for that class.

Each instance of the class contains a hidden pointer, often called the vptr (virtual table pointer), that points to the class's vtable.

When a virtual function is called on an object, the program uses the vptr to look up the correct function in the vtable and invokes it.

Here’s a simple example:

#include <iostream>
#include <string>

class Base {
public:
  virtual void Speak() {
    std::cout << "Base speaking\n";
  }
};

class Derived : public Base {
public:
  void Speak() override {
    std::cout << "Derived speaking\n";
  }
};

void CallSpeak(Base& obj) {
  obj.Speak(); 
}

int main() {
  Base base;
  Derived derived;

  CallSpeak(base); 
  CallSpeak(derived); 
}
Base speaking
Derived speaking

In this example:

  • Base has a virtual function Speak().
  • Derived overrides Speak().

As a result, two vtables are created:

  • Base has a vtable with an entry pointing to Base::Speak().
  • Derived has its own vtable with an entry pointing to Derived::Speak().

These vtables are checked when we call class methods:

  • When CallSpeak(base) is called, the vptr in base points to the Base vtable, and Base::Speak() is invoked.
  • When CallSpeak(derived) is called, the vptr in derived points to the Derived vtable, and Derived::Speak() is invoked.

Benefits of Vtables

  • Polymorphism: Vtables enable polymorphism by allowing the correct function to be called based on the actual type of the object, not the type of the reference or pointer used to call the function.
  • Dynamic Binding: They support dynamic binding, meaning the function to be called is determined at runtime based on the object's vtable.

Considerations

  • Overhead: There is a slight overhead in terms of memory and performance due to the vtable and vptr. Each object with virtual functions carries an extra pointer, and each virtual call requires an additional indirection to look up the function pointer in the vtable.
  • Complexity: The mechanism adds complexity to the program's runtime behavior and can make debugging more challenging.

Despite the overhead, vtables are crucial for implementing polymorphism in C++, providing flexibility and enabling powerful design patterns.

This Question is from the Lesson:

Pure Virtual Functions

Learn how to create interfaces and abstract classes using pure virtual functions

Answers to questions are automatically generated and may not have been reviewed.

This Question is from the Lesson:

Pure Virtual Functions

Learn how to create interfaces and abstract classes using pure virtual functions

A computer programmer
Part of the course:

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Free, unlimited access

This course includes:

  • 125 Lessons
  • 550+ Code Samples
  • 96% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved