C++ 中的虚函数和多态是如何实现的?
C++ 中的虚函数和多态是如何实现的?
推荐答案
C++ 虚函数与多态的实现机制
总结性回答
C++ 中的虚函数和多态主要通过虚函数表(vtable)和虚指针(vptr)机制实现。当类中包含虚函数时,编译器会为该类生成一个虚函数表,其中存储了该类所有虚函数的地址。每个对象会包含一个指向该表的虚指针。通过这种间接调用机制,实现了运行时的多态行为。
详细解释
1. 虚函数表(vtable)机制
- 每个包含虚函数的类都有一个虚函数表
- 虚函数表是一个函数指针数组,存储了该类所有虚函数的地址
- 虚函数表在编译时生成,存放在程序的只读数据段
- 派生类会继承基类的虚函数表,并可以覆盖其中的函数指针
2. 虚指针(vptr)机制
- 每个包含虚函数的类的对象都有一个隐藏的虚指针成员
- 虚指针指向该对象所属类的虚函数表
- 虚指针在对象构造时被初始化,指向正确的虚函数表
3. 多态调用过程
当通过基类指针或引用调用虚函数时:
- 通过对象的虚指针找到虚函数表
- 在虚函数表中查找对应的函数指针
- 通过函数指针调用实际的函数实现
这种间接调用机制使得:
- 基类指针可以调用派生类的实现
- 调用哪个函数在运行时决定(动态绑定)
- 实现了"一个接口,多种实现"的多态特性
4. 内存布局示例
class Base {
public:
virtual void func1() {}
virtual void func2() {}
int data;
};
class Derived : public Base {
public:
void func1() override {}
virtual void func3() {}
int derived_data;
};
5. 性能考虑
虚函数调用比普通函数调用多一次间接寻址,会有轻微的性能开销:
- 需要读取虚指针
- 需要读取虚函数表
- 然后才能跳转到实际函数
但在现代CPU上,这种开销通常很小,且分支预测能很好处理这种情况。