1、多态行为
当有一个基类,并且该基类指针指向一个派生类对象,并且希望删除这个对象时,必须将基类的析构函数声明为 虚析构函数。这样可以确保正确地调用派生类的析构函数,这对于正确的内存管理和资源清理非常重要。
#include<iostream> using namespace std; class Base { public: // 虚析构函数 virtual ~Base() { std::cout << "Base class destructor called\n"; } // 普通成员函数 virtual void show() { std::cout << "Base class show function\n"; } }; class Derived : public Base { public: // 派生类的析构函数 ~Derived() override { std::cout << "Derived class destructor called\n"; } // 重写基类的成员函数 void show() override { std::cout << "Derived class show function\n"; } }; int main() { // 使用基类指针指向派生类对象 Base* basePtr = new Derived(); // 调用 show 方法,表现出多态行为 basePtr->show(); // 删除对象,确保正确调用派生类的析构函数 delete basePtr; return 0; }
2、基类指针删除派生类对象
如通过指向基类的指针删除对象,基类的析构函数应该是 虚函数,这样确保基类和派生类的析构函数都会被正确调用。如果没有虚析构函数,只有基类的析构函数会被调用,这可能导致派生类分配的资源没有被释放。
#include<iostream> using namespace std; class Base { public: virtual ~Base() { // 虚析构函数 std::cout << "Base destructor\n"; } }; class Derived : public Base { public: ~Derived() override { std::cout << "Derived destructor\n"; } }; int main() { Base* b = new Derived(); delete b; // 将正确调用 Derived 的析构函数,再调用 Base 的析构函数 }
3、析构函数的资源清理
在使用继承和动态内存分配时,基类的析构函数应该是虚析构函数,确保在删除对象时所有资源都能被正确清理。当派生类分配了资源(如动态内存、文件句柄或其他系统资源)时,这尤其重要。
4、非多态类
如从不打算通过基类指针删除派生类对象(即不使用多态),则不需要虚析构函数。在这种情况下,使用 非虚析构函数 就足够了,并且它会稍微提高效率。
5、性能考虑
虚析构函数会带来一些小的性能开销,因为需要进行虚函数表(vtable)查找。然而,这个开销通常是微不足道的,确保正确清理的好处远大于这个小小的性能成本。