1. 为什么需要虚析构函数?
第一次遇到内存泄漏问题时,我盯着任务管理器里不断攀升的内存曲线百思不得其解。那是一个多态场景下的资源管理问题——当通过基类指针删除子类对象时,子类的析构函数竟然没有被调用!这个看似简单的机制背后,隐藏着C++对象生命周期管理的重要原理。
虚析构函数的核心价值在于保证多态继承体系中对象的完整销毁。当基类指针指向子类对象时,如果基类析构函数不是虚函数,那么通过该指针delete对象时,编译器只会调用基类的析构函数。这会导致子类独有的资源(如动态内存、文件句柄、网络连接等)无法被正确释放,形成典型的内存泄漏。
关键认知:析构函数的虚特性会遗传给所有子类。这意味着只要基类声明了虚析构函数,所有子类的析构函数自动成为虚函数(无论是否显式使用virtual关键字)。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 虚析构函数的工作原理
2.1 虚函数表机制
每个包含虚函数的类都会有一个虚函数表(vtable),其中存储着该类所有虚函数的指针。当类中存在虚析构函数时,vtable会包含两个关键条目:
- 完整对象析构函数(complete object destructor)
- 删除析构函数(deleting destructor)
以下是一个典型的多态继承案例:
cpp复制class Base {
public:
virtual ~Base() { cout << "Base destroyed" << endl; }
};
class Derived : public Base {
public:
~Derived() override { cout << "Derived destroyed" << endl; }
};
int main() {
Base* obj = new Derived();
delete obj; // 正确调用Derived和Base的析构函数
}
当通过基类指针删除对象时,实际调用流程为:
- 通过vtable查找析构函数地址
- 先调用子类析构函数
- 再调用基类析构函数
- 最后释放对象内存
2.2 对象销毁的完整过程
没有虚析构函数时,对象销毁过程是不完整的。假设去掉上面例子中的virtual关键字:
- 仅输出"Base destr
