基类析构函数必须声明为virtual,否则通过基类指针delete派生类对象时仅调用基类析构函数,导致派生类资源未释放、内存泄漏;虚析构确保按“派生类→基类”顺序完整析构。

当用基类指针指向派生类对象,并通过该指针 delete 对象时,若基类析构函数不是虚函数,只会调用基类的析构函数,派生类的析构逻辑(比如释放资源、关闭文件、删除堆内存等)将被跳过——这直接导致内存泄漏或资源未释放问题。
虚析构函数的作用:确保正确析构整个对象
虚析构函数让析构行为具备多态性。只要基类析构函数声明为 virtual,即使通过基类指针删除派生类对象,也会按“派生类 → 基类”的顺序逐层调用所有析构函数。
- 没有 virtual:只调用基类析构,派生类中 new 出的内存、打开的句柄等不会被清理
- 有 virtual:先执行派生类析构体(释放专属资源),再自动调用基类析构
- 规则:只要一个类设计为多态基类(即有 virtual 函数,且可能被继承并用基类指针管理生命周期),其析构函数就应声明为 virtual
不写虚析构函数的真实后果示例
假设:
class Base { public: ~Base() { cout class Derived : public Base {int* p = new int[100];
public:
~Derived() { delete[] p; cout };
执行:
Base* ptr = new Derived();
delete ptr; // 输出只有 "Base dtor",p 指向的 100 个 int 永远泄露
立即学习“C++免费学习笔记(深入)”;
哪些情况必须加 virtual ~Base()?
- 类中已有至少一个 virtual 成员函数(说明它被当作接口/基类使用)
- 你打算用 new 派生类对象,再用基类指针持有并 delete(典型多态资源管理场景)
- 类被设计为抽象基类(含纯虚函数),哪怕没数据成员也要加,否则子类对象无法安全销毁
- 标准建议:如果类有 virtual 函数,析构函数就该是 virtual;如果类不打算被继承,可加 final 或不提供虚函数
小技巧与常见误区
- 虚析构函数可以是纯虚的(virtual ~Base() = 0;),但必须在类外提供定义(哪怕空实现),否则链接失败
- 构造函数不能是虚函数,但析构函数可以且经常需要是虚的——这是 C++ 中唯一推荐普遍使用虚函数的析构场景
- std::unique_ptr
也受此规则约束:若 Base 析构非虚,用它管理 Derived 对象仍会漏掉派生部分析构 - 不是所有基类都需要虚析构:仅当存在“通过基类指针 delete 派生对象”这一需求时才需要











