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)查找。然而,这个开销通常是微不足道的,确保正确清理的好处远大于这个小小的性能成本。