何时使用虚拟析构函数?

我对大多数OOP理论都有很好的理解,但有一件事让我很困惑,那就是虚拟析构函数

我认为析构函数总是被调用,不管是什么,对于链中的每个对象

你打算什么时候让它们虚拟化,为什么

当您可能通过指向基类的指针删除派生类的实例时,虚拟析构函数非常有用:

类基
{
//一些虚拟方法
};
派生类:公共基
{
~Derived()
{
//做一些重要的清理工作
}
};

在这里,您会注意到我没有将Base的析构函数声明为virtual。现在,让我们看一下以下代码片段:

Base*b=new-Derived();
//使用b
删除b;//问题来了!

由于Base的析构函数不是虚拟的,b是指向派生对象的Base*delete b具有未定义的行为:

[在中删除b],如果
要删除的对象与其动态类型(静态)不同
类型应为待处理对象的动态类型的基类
已删除且静态类型应具有虚拟析构函数或
行为未定义

在大多数实现中,对析构函数的调用将像任何非虚拟代码一样进行解析,这意味着将调用基类的析构函数,而不是派生类的析构函数,从而导致资源泄漏

总而言之,当基类的析构函数要进行多态操作时,一定要使它们成为虚拟的

如果要防止通过基类指针删除实例,可以使基类析构函数受保护且非虚拟;这样,编译器就不会让您对基类指针调用delete

在本文中,您可以从Herb Sutter了解有关虚拟性和虚拟基类析构函数的更多信息

发表评论