C++利用虚表来实现对虚函数的调用。
每个使用虚函数的class都有一张单独的虚函数表,虚函数表是在编译时候创建的静态数组。每个虚函数在虚函数表中都包含一个入口,类的实例可以调用虚函数的入口,虚函数的入口其实就是一个函数指针。
当一个class创建一个实例时,编译器就添加了一个指向基类的隐藏指针(*__vptr)。*__vptr是一个真实的指针,被子类继承。不像*this只是一个函数的参数,*this是编译器用于解决自身引用的问题。
到底怎么实现的呢?我们来看个例子
代码中有3个class,编译器将建3个虚函数表:基类的虚表,D1的虚表,D2的虚表.
编译器将自动给含有虚函数的基类添加一个隐藏指针(*__vptr),例如:
当创建一个对象时,*__vptr就指向了类的虚函数表。比如,基类对象创建的时候,*__vptr就i指向基类的虚函数表。D1对象创建的时候,*__vptr就i指向D1的虚函数表。D2对象创建的时候,*__vptr就i指向D2的虚函数表。
虚函数表是如何赋值的呢?因为这里有2个虚函数,所以这里就有2个入口(一个是function1()的入口,另一个是function2()的入口)
Base的虚函数比较简单,Base的对象只需要访问Base的成员。function1()的入口指向Base::function1(),function2()的入口指向Base::function2()。
D1的虚函数表稍微复杂点。D1的对象可以访问Base的成员。function1()的入口指向D1::function1(),function2()的入口指向Base::function2()。
D2的虚函数表与D1的虚函数表相似,只不过function1()的入口指向Base::function1(),function2()的入口指向D2::function2()。