只有当类可能被多态删除(即通过基类指针调用delete)时才必须声明虚析构函数;否则如无继承、仅值语义使用、final类或对象均以具体类型管理,则可不用,避免vptr开销和间接调用成本。

不需要。只有当类被设计为基类、且存在通过基类指针或引用删除派生类对象的可能时,才必须声明虚析构函数。
什么情况下可以不用虚析构函数
以下场景中,~Base() 完全可以是非虚的:
- 类没有被继承(即没有
class Derived : public Base {}这类用法) - 类虽有派生,但所有对象都以具体类型创建和销毁(如
Derived d;或std::unique_ptr<derived></derived>),从不通过Base*或Base&删除 - 类是 final 的(
class Base final { ... };),编译器禁止继承 - 类仅用于值语义(如作为容器元素、函数参数传值),不涉及多态指针管理
为什么有人误以为“所有基类都要加 virtual”
这是对“只要可能被继承,就该加虚析构”的过度泛化。真实约束是:「只要可能被多态删除,就必须加」。常见混淆点:
-
std::vector<base>存的是对象副本,不是指针,vector析构时调用的是Base的析构函数,跟虚不虚无关 -
std::unique_ptr<base>确实会触发多态删除,但前提是它被初始化为指向派生类对象(如std::make_unique<derived>()</derived>),否则仍只调用Base::~Base() - 纯接口类(如
class Shape { public: virtual ~Shape() = 0; };)必须有虚析构,哪怕没数据成员——因为它的存在意义就是被继承和多态使用
加了虚析构但没多态删除,有什么代价
有,虽然小,但真实存在:
- 每个对象增加一个
vptr(通常 8 字节),影响缓存局部性和内存占用 - 每次调用析构函数需一次间接寻址(查 vtable),比直接调用略慢(现代 CPU 下差异微乎其微,但硬实时系统需留意)
- 若类被频繁构造/析构(如粒子系统中的小对象),这些开销会累积
- 非虚析构函数可被内联,虚析构函数不能
怎么判断自己是否真的需要虚析构
盯住两件事:
- 有没有
Base* p = new Derived();或等价形式(如工厂函数返回Base*) - 有没有
delete p;(或std::default_delete被触发,比如std::shared_ptr<base>持有派生对象)
两者同时成立,就必须加 virtual;缺一不可。其他情况加了只是冗余,还悄悄拖慢性能。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











