贝利信息

c++虚函数的作用_c++多态实现原理分析

日期:2026-01-07 00:00 / 作者:冰火之心
虚函数实现运行时多态,通过vtable和vptr支持动态绑定;纯虚函数定义抽象接口;析构函数通常须声明为virtual以防内存泄漏。

虚函数让父类指针能调用子类重写的方法

没有 virtual,父类指针或引用调用函数时,编译器在编译期就绑定到父类版本(静态绑定);加了 virtual,运行时才根据实际对象类型决定调用哪个函数(动态绑定)。这是实现「接口统一、行为各异」的核心机制。

常见错误现象:

Base* p = new Derived();
p->func(); // 如果 func() 没声明为 virtual,调用的是 Base::func(),不是 Derived::func()

vtable 和 vptr 是多态的底层支撑

C++ 编译器为每个含虚函数的类生成一张虚函数表(vtable),表中存的是该类所有虚函数的地址。每个该类的对象开头隐式插入一个指针(vptr),指向其所属类的 vtable。运行时通过 vptr 查表跳转,完成动态分派。

关键细节:

纯虚函数强制派生类实现,构成抽象接口

声明为 virtual void func() = 0; 的函数叫纯虚函数,含纯虚函数的类叫抽象类,不能实例化。它不提供默认实现,只定义契约。

立即学习“C++免费学习笔记(深入)”;

使用场景:

析构函数几乎总是应该声明为 virtual

如果基类析构函数不是 virtual,用 Base* 删除派生类对象会导致子类部分内存泄漏——只调用了 Base::~Base(),而 Derived::~Derived() 根本不会执行。

正确写法:

class Base {
public:
    virtual ~Base() = default; // 或空实现,但不能省略 virtual
};

例外情况:类明确设计为不作基类(如 final 类)、或性能极端敏感且确定不会通过基类指针销毁对象时,可不加。但绝大多数带虚函数的基类,都应把析构设为 virtual

容易忽略的一点:即使基类没有数据成员、只有虚函数,只要它可能作为多态基类被 delete,就必须有 virtual 析构——否则行为未定义,而编译器通常不报错。