在c++中,基类的析构函数应该声明为虚函数,主要是为了确保通过基类指针删除派生类对象时,能够正确调用派生类的析构函数,避免资源泄漏和未定义行为。
对象销毁时的析构顺序问题
当一个派生类对象通过基类指针被删除时,如果基类的析构函数不是虚函数,那么只会调用基类的析构函数,而不会调用派生类的析构函数。这会导致派生类中分配的资源(如内存、文件句柄等)得不到释放。
例如:
class Base { public: ~Base() { std::cout << "Base destructorn"; } }; <p>class Derived : public Base { public: ~Derived() { std::cout << "Derived destructorn"; } };</p><p>int main() { Base* ptr = new Derived(); delete ptr; // 只会调用 Base::~Base() }</p>
输出结果只有 “Base destructor”,Derived 的析构函数没有被调用,可能造成资源泄漏。
立即学习“C++免费学习笔记(深入)”;
虚析构函数保证完整清理
将基类的析构函数设为虚函数后,C++的动态绑定机制会确保正确调用派生类的析构函数,然后自动调用基类的析构函数。
修改上面的例子:
class Base { public: virtual ~Base() { std::cout << "Base destructorn"; } }; <p>class Derived : public Base { public: ~Derived() { std::cout << "Derived destructorn"; } };</p>
此时 delete ptr 会先调用 Derived::~Derived(),再调用 Base::~Base(),实现完整的资源清理。
多态使用场景下的必要性
只要类可能被继承,并且程序设计中允许通过基类指针管理派生类对象(这是多态的常见用法),就必须将析构函数设为虚函数。
即使基类本身没有需要释放的资源,也不能排除派生类会添加成员变量或动态资源。不设为虚析构函数会埋下隐患。
标准做法是:如果类有虚函数(表明它用于多态),就应提供虚析构函数。