Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do we need a virtual table?

Tags:

c++

vtable

I was looking for some information about virtual tables, but I can't find anything that is easy to understand.

Can somebody give me good examples with explanations?

like image 584
lego69 Avatar asked Jun 09 '10 09:06

lego69


People also ask

What do you mean by virtual table?

A virtual table is a set of columns that have specific names and data types. These columns describe the format of data that flows into and out of an operator. Each operator port in a data flow operator has a virtual table that defines the structure of the data coming into or leaving that port.

What is meant by virtual table in SQL?

In SQL, a view is a virtual table based on the result-set of an SQL statement. A view contains rows and columns, just like a real table. The fields in a view are fields from one or more real tables in the database.

What happens when virtual table is created?

The vtable is created at compile time. When a new object is created during run time, the hidden vtable pointer is set to point to the vtable. Keep in mind, though, that you can't make reliable use if the virtual functions until the object is fully constructed.

What is the advantage of virtual function?

The main advantage of virtual functions are that they directly support object oriented programming. When you declare a function as virtual you're saying that exactly what code is executed depends on the type of the object you call it against. you can't tell exactly what code path it's going to follow.


2 Answers

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).

like image 74
Frerich Raabe Avatar answered Oct 26 '22 10:10

Frerich Raabe


The virtual function table is an implementation detail - it's how the compiler implements polymorphic methods in classes.

Consider

class Animal
{
   virtual void talk()=0;
}

class Dog : Animal
{
   virtual void talk() {
       cout << "Woof!";
   }
}

class Cat : Animal
{
   virtual void talk() {
       cout << "Meow!";
   }
}

And now we have

   A* animal = loadFromFile("somefile.txt"); // from somewhere
   animal->talk();

How do we know which version of talk() is called? The animal object has a table that points to the virtual functions that are used with that animal. For example, talk may be at the 3rd offset, if there are two other virtual methods:

   dog
   [function ptr for some method 1]
   [function ptr for some method 2]
   [function ptr for talk -> Dog::Talk]

   cat
   [function ptr for some method 1]
   [function ptr for some method 2]
   [function ptr for talk -> Cat::Talk]

When we have an instance of Animnal, we don't know which talk() method to call. We find it by looking in the virtual table and fetching the third entry, since the compiler knows that corresponds to the talk pointer (the compiler knows the virtual methods on Animal, and so knows the order of pointers in the vtable.)

Given an Animal, to call the right talk() method, the compiler adds code to fetch the 3rd function pointer and use that. This then directs to the appropriate implementation.

With non-virtual methods, this is not necessary since the actual function being called can be determined at compile time - there is only one possible function that can be called for a non-virtual call.

like image 40
mdma Avatar answered Oct 26 '22 10:10

mdma