(你可能会有一个疑问:编译器是如何实现虚函数的呢?)
虚表:
- 每个多态类有一个虚表(virtual table)
- 虚表中有当前类的各个虚函数的入口地址
- 每个对象有一个指向当前类的虚表的指针(虚指针vptr)
动态绑定的实现:
- 构造函数中为对象的虚指针赋值
- 通过多态类型的指针或引用调用成员函数时,通过虚指针找到虚表,进而找到所调用的虚函数的入口地址
- 通过该入口地址调用虚函数
样例:(图表与程序对应)
#include<iostream>
class Base
{
public:
virtual void F() { printf("F1\n"); }
virtual void G() { printf("G1\n"); }
private:
int i;
};
class Derived: public Base
{
public:
virtual void F() { printf("F2\n"); }
virtual void H() { printf("H2\n"); } //新增的虚函数
private:
int j;
};
int main(void)
{
Base p;
Derived q;
printf("%d %d\n", sizeof(p), sizeof(q)); //输出结果:8 12,因为有一个隐藏的指向虚函数表的指针
return 0;
}