1

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

所以问题是 1. 现在考虑三个规则,我们应该声明另外两个吗?

4

5 回答 5

4

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

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

不过,最后一条规则只是一个经验法则。即使一个类没有任何其他虚函数,也可能需要在一个类中拥有一个虚析构函数,相反,如果多态类从未在需要这个的上下文中使用它,则它可能不需要虚析构函数(通常会制作protected或什private至强制执行析构函数)。

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

于 2012-07-27T05:32:36.817 回答
2

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

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

于 2012-07-27T05:37:43.460 回答
2

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

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

于 2012-07-27T05:14:24.520 回答
1

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

然而,从实际的角度来看,您几乎没有理由不声明析构函数 virtual 并且应该为您认为可以用作基础的任何类执行它。

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

另请注意,根据我的经验,当您具有继承和多态性时,C++ 的复制语义甚至静态类型有时会感觉不对。

于 2012-07-27T05:41:37.463 回答
0

Any class that could be a base class a some point should have it's destructor declared virtual. Independent of wheter another member function is virtual or not.

The rule of three says that you should declare a

  • destructor
  • copy constructor
  • copy assignment operator

if you declare one of them. Independantly of whether the destruction is virtual.

于 2012-07-27T05:16:35.833 回答