C++为每个类对象添加一个隐藏成员,这个成员就是虚函数表指针。虚函数表可以理解成一个表格,里面存放了类中的虚函数指针。我们可以通过虚函数表找到需要调用的虚函数。
一、存储
虚函数表指针位于类存储的最前面4个字节,编译期生成,运行期载入。
假设存在A类,则其存储如下:
A的虚函数表指针 |
A的属性a |
A的属性b |
…… |
而其中A的虚函数表指针指向的内存存储如下:
虚函数A::func1地址 |
虚函数A::func2地址 |
虚函数A::func3地址 |
虚函数A::func4地址 |
…… |
现有B类继承自A类,则其存储如下:
B的虚函数表指针 |
B的属性a |
B的属性b |
…… |
A的属性a |
A的属性b |
…… |
假设B类中重写了虚函数func1,则其虚函数表如下:
虚函数B::func1地址 |
虚函数A::func2地址 |
虚函数A::func3地址 |
虚函数A::func4地址 |
…… |
备注:多继承有多个虚函数表指针。
二、举例
现有代码如下:
A* pa = new B();
pa->func1();
则其func1的调用过程如下:
1.去除pa指针的前4个字节,即它的虚函数表指针。因为是B类的对象,所以此处是B的虚函数表指针。如果是A类对象,则为A类的虚函数表指针。
2.再在虚函数表中找到对应的虚函数func1的地址。
3.通过函数地址调用虚函数。
注意事项:子类独有的虚函数,不要通过父类指针的方式调用,编译会报错。但是,通过指针的方式,我们确实可以调用虚函数表中,子类特有虚函数。