父类具有Virtual函数.是否需要在父类中具有虚拟析构函数

Parent class has a Virtual function. Is it necessary to have a virtual destructor in the parent class?

本文关键字:父类 析构函数 虚拟 是否 Virtual 函数      更新时间:2023-10-16

父类有一个Virtual函数。是否有必要在父类中设置虚拟析构函数?

所以问题是1.现在考虑第三条规则,我们是否应该宣布另外两条规则?

每当对指向要删除的对象实际上是更派生类型的类的指针调用delete时,都需要虚拟析构函数。如果您的基类可能在这种情况下使用,那么您必须提供一个虚拟析构函数。

通常建议向具有虚拟函数的任何类添加虚拟析构函数,因为这为该类的未来用户提供了安全性和灵活性,并且向已经多态的类添加虚拟析构函数的额外成本通常很低。

不过,最后一条规则只是经验法则。类中可能需要有一个虚拟析构函数,即使它没有任何其他虚拟函数。相反,如果多态类从未在需要它的上下文中使用过,那么它可能不需要虚拟析构因子(通常析构函数会被设置为protected甚至private来强制执行这一点)。

如果编译器提供的默认实现不能做正确的事情,那么只需要提供一个用户定义的复制构造函数和一个复制赋值运算符。如果您添加了一个带有空实现的析构函数,纯粹是为了使其成为虚拟的,那么这不太可能与您提供复制构造函数和复制赋值运算符的需求有关。

在类中拥有虚拟析构函数的唯一真正原因是,如果您计划以多形态删除该类的对象,即,如果您打算通过指向基类的指针来delete派生类的对象。如果从不这样做,就不需要虚拟析构函数。

然而,如果您的类中已经有了一个虚拟函数,那么使析构函数成为虚拟函数就不会产生明显的开销(因为VMT指针已经被引入到对象中)。在这种情况下,使析构函数成为虚拟的可能是个好主意。以防万一。

具有虚拟函数的类具有虚拟析构函数是有意义的,因为它是一个被设计为从中继承并可能以多态方式使用的类(请参阅相关的SO问题)。如果它是多态使用的,从某种意义上说,指向父类的指针指向派生类型的实例,那么父类必须具有虚拟析构函数。

另一方面,只有当父类的类析构函数确实做了编译器合成的析构函数不会做的事情(例如,显式处理某些资源的释放)时,才有必要在父类中遵循三规则。如果父类的析构函数是琐碎的,并且仅声明为允许从父类指针正确销毁多态对象,则无需提供其复制构造函数和复制赋值运算符。

从技术上讲,只有当您要以多态方式删除实例时,才必须具有虚拟析构函数。换句话说,您可以在没有虚拟析构函数的情况下使用虚拟方法。

然而,从实用的角度来看,很少有理由不声明析构函数为虚拟的,而且应该对任何你认为可以用作基的类进行声明。

第三条规则是关于程序逻辑:如果析构函数、复制构造函数或赋值中的任何一个都有逻辑,那么您可能需要这三个函数中的逻辑。然而,请注意,从形式的角度来看,这并不是一条严格的规则,在极少数情况下,它根本不适用(例如,我可能有兴趣在日志中看到每个创建对象的一行,但不是在分配或销毁时)。

还要注意的是,根据我的经验,当你有继承和多态性时,C++的复制语义甚至静态类型有时会感觉不对劲。

任何在某个点上可能是基类的类都应该将其析构函数声明为虚拟的。独立于另一个成员功能是否是虚拟的。

三条规则说你应该申报

  • 析构函数
  • 复制构造函数
  • 复制分配运算符

如果你申报其中一个。与破坏是否是虚拟的无关。