C++ 中的虚函数和多态是如何实现的?

C++后端

C++ 中的虚函数和多态是如何实现的?

推荐答案

C++ 虚函数与多态的实现机制

总结性回答

C++ 中的虚函数和多态主要通过虚函数表(vtable)和虚指针(vptr)机制实现。当类中包含虚函数时,编译器会为该类生成一个虚函数表,其中存储了该类所有虚函数的地址。每个对象会包含一个指向该表的虚指针。通过这种间接调用机制,实现了运行时的多态行为。

详细解释

1. 虚函数表(vtable)机制

  • 每个包含虚函数的类都有一个虚函数表
  • 虚函数表是一个函数指针数组,存储了该类所有虚函数的地址
  • 虚函数表在编译时生成,存放在程序的只读数据段
  • 派生类会继承基类的虚函数表,并可以覆盖其中的函数指针

2. 虚指针(vptr)机制

  • 每个包含虚函数的类的对象都有一个隐藏的虚指针成员
  • 虚指针指向该对象所属类的虚函数表
  • 虚指针在对象构造时被初始化,指向正确的虚函数表

3. 多态调用过程

当通过基类指针或引用调用虚函数时:

  1. 通过对象的虚指针找到虚函数表
  2. 在虚函数表中查找对应的函数指针
  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上,这种开销通常很小,且分支预测能很好处理这种情况。