You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

当基类与子类均使用默认析构函数时,基类仍需虚析构函数吗?

基类有虚函数但用默认析构时,要不要加虚析构?

嘿,这个问题问到点子上了!很多人以为只有子类有自定义析构的时候才需要虚析构,其实不是这么回事——咱们得从多态销毁的核心规则说起:

核心场景:通过基类指针删除子类对象

只要你会用到「基类指针/引用指向子类对象,然后通过这个指针删除对象」的场景,不管子类有没有自定义析构函数,基类都必须有虚析构函数。否则这会触发C++标准里的未定义行为——哪怕子类的默认析构看起来只是“啥也没做”,也不能掉以轻心。

举个你给出的代码例子,稍微补全一下问题场景:

#include <string>
using namespace std;

class Printable { 
public:
    virtual string print() = 0; 
    // 这里没有虚析构函数
    ~Printable() = default; // 普通的默认析构
}; 

class A : public Printable { 
    int foo; 
    bool bar; 
    string str; 
public:
    string print() override { return "A"; }
    // 子类用默认析构
}; 

int main() {
    Printable* ptr = new A();
    delete ptr; // 这里是未定义行为!
    return 0;
}

这段代码里,A的析构是默认的,但因为Printable的析构不是虚的,编译器不会沿着继承链调用A的析构——虽然A的成员都是基础类型或STL容器(STL容器自己会管理资源),看起来可能不会出问题,但未定义行为意味着程序可能崩溃、内存泄漏,或者表现出任何奇怪的行为,这绝对是要避免的。

为什么有虚函数的基类建议加虚析构?

既然你的Printable类已经有了虚函数print(),说明它就是为多态设计的——大概率会出现基类指针指向子类对象的场景。这时候给基类加虚析构是零成本的最佳实践:

  • 只要基类的析构被声明为虚的,子类的默认析构会自动成为虚析构(继承特性);
  • 编译器会自动生成正确的虚析构逻辑,保证销毁对象时从子类到基类的析构函数都被调用;
  • 完全不会带来额外的性能负担(除非你在极端性能敏感的场景,但这种场景一般也不会用多态)。

什么时候可以不用?

如果你的基类虽然被继承,但永远不会通过基类指针/引用删除子类对象,理论上可以不用虚析构。但说实话,这种场景非常少见——既然已经给基类加了虚函数,就说明你是要用到多态的,与其赌“永远不会这么用”,不如直接加上虚析构,彻底避免踩坑。

总结一下:只要你的基类是多态基类(有虚函数),不管子类有没有自定义析构,都应该给基类声明虚析构函数。

内容的提问来源于stack exchange,提问作者Jackson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:42:56