Why do we need a virtual table?

Without virtual tables you wouldn’t be able to make runtime polymorphism work since all references to functions would be bound at compile time. A simple example

struct Base {
  virtual void f() { }
};

struct Derived : public Base {
  virtual void f() { }
};

void callF( Base *o ) {
  o->f();
}

int main() {
  Derived d;
  callF( &d );
}

Inside the function callF, you only know that o points to a Base object. However, at runtime, the code should call Derived::f (since Base::f is virtual). At compile time, the compiler can’t know which code is going to be executed by the o->f() call since it doesn’t know what o points to.

Hence, you need something called a “virtual table” which is basically a table of function pointers. Each object that has virtual functions has a “v-table pointer” that points to the virtual table for objects of its type.

The code in the callF function above then only needs to look up the entry for Base::f in the virtual table (which it finds based on the v-table pointer in the object), and then it calls the function that table entry points to. That might be Base::f but it is also possible that it points to something else – Derived::f, for instance.

This means that due to the virtual table, you’re able to have polymorphism at runtime because the actual function being called is determined at runtime by looking up a function pointer in the virtual table and then calling the function via that pointer – instead of calling the function directly (as is the case for non-virtual functions).

Leave a Comment