基类有虚析构但派生类未定义析构时,销毁派生对象会怎样?
关于虚析构与派生类默认析构的问题解答
嘿,这个问题问得特别关键,刚好戳中了C++多态析构和编译器自动生成函数的核心细节!咱们一步步拆解来看:
核心结论先给你
当基类有virtual析构函数,而派生类没有显式定义析构函数时:
- 编译器会自动为派生类生成一个默认析构函数
- 这个默认析构函数会继承基类析构的
virtual属性,所以通过基类指针delete派生对象时,会正确触发派生类的默认析构,再调用基类的析构 - 只要派生类没有需要手动释放的自定义资源,默认析构就能完美处理资源释放;如果有自定义资源,就得显式写析构来清理
具体细节拆解
1. 编译器自动生成的默认析构函数
C++标准规定:如果一个类没有显式定义析构函数,编译器会自动生成一个公有的、无参的默认析构函数。这个函数的行为是:
- 依次调用类中所有非静态成员对象的析构函数
- 最后调用直接基类的析构函数(如果有继承关系)
而且因为你的基类Base的析构是virtual的,派生类Derived的默认析构函数也会自动成为virtual的——虚函数的属性是会被继承的,哪怕你没显式写virtual关键字。
2. 多态下的析构流程
回到你的代码,当执行delete d;(d是Base*指向Derived对象)时:
- 因为基类析构是
virtual,所以会根据对象的实际类型(Derived)调用对应的析构函数,也就是编译器为Derived生成的默认析构 Derived的默认析构会先清理自己的成员(你的例子里Derived没有自定义成员,这一步相当于空操作)- 然后自动调用基类
Base的虚析构函数,输出Base Destructor called
3. 资源释放的正确性
- 如果
Derived没有持有需要手动管理的资源(比如没有用new分配的堆内存、没有打开的文件句柄、没有第三方库的资源句柄等),默认析构完全能正确释放所有资源——成员对象的析构会被自动调用,基类的资源也会被基类析构清理。 - 如果
Derived有自己的动态资源(比如Derived里有个int* ptr = new int;),那必须显式定义析构函数来释放delete ptr;,否则编译器生成的默认析构不会处理这种自定义资源,会造成内存泄漏——这和基类有没有虚析构无关,是派生类自己的析构责任。
验证示例
把你的代码修改成派生类不写析构的版本:
#include <iostream> class Base { public: virtual void fun() { std::cout << "Base Fun" << std::endl; }; virtual ~Base() { std::cout << "Base Destructor called" << std::endl; }; }; class Derived : public Base { public: virtual void fun() { std::cout << "Derived Fun" << std::endl; }; // 这里去掉了显式的析构函数 }; int main() { Base* b = new Base(); Base* d = new Derived(); b->fun(); d->fun(); delete b; delete d; return 0; }
运行输出会是:
Base Fun Derived Fun Base Destructor called Base Destructor called
虽然看不到Derived析构的输出,但它确实被调用了——只是默认析构没有输出语句而已。如果给Derived加个成员对象(比如std::string s;),你会看到std::string的析构也被正确触发。
内容的提问来源于stack exchange,提问作者Proxified
相关产品推荐
相关产品推荐

