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).
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…