父类具有虚函数。是否有必要在父类中使用虚拟析构函数?
所以问题是 1.现在考虑三个规则,我们应该宣布其他两个吗?
答案 0 :(得分:4)
虚拟析构函数必需在指向该类的指针上随时调用delete
,其中被删除的对象实际上是更多派生类型。如果您的基类可能在这种情况下使用,那么您必须提供虚拟析构函数。
通常建议将虚拟析构函数添加到具有虚函数的任何类中,因为这为该类的未来用户提供了安全性和灵活性,并且向已经多态的类添加虚拟析构函数的额外成本通常很低。 / p>
这最后一条规则只是一个经验法则。即使它没有任何其他虚函数,也可能需要在类中包含虚拟析构函数,相反,如果从不在需要此类的上下文中使用多态类,则可能不需要虚拟析构函数(通常会将析构函数设为protected
甚至private
来强制执行此操作。
如果编译器提供的默认实现不能正确执行,您只需要提供用户定义的复制构造函数和复制赋值运算符。如果你添加了一个带有空实现的析构函数,纯粹是为了使它成为虚拟的,那么这不太可能影响你需要提供一个复制构造函数和一个复制赋值操作符。
答案 1 :(得分:2)
具有虚函数的类具有虚拟析构函数是有意义的,因为它是一个设计为从多态继承并可能使用的类(参见related SO question)。如果它以多态方式使用,在指向父类的指针指向派生类型的实例的意义上,则父类必须具有虚拟析构函数。
另一方面,如果父类的析构函数实际上做了编译器合成的一个不会做的事情(例如明确处理某些资源的释放),那么只需要在父类中遵循三条规则。 )。如果父级的析构函数是微不足道的,并且只声明允许从父类指针正确销毁多态对象,则不需要提供其复制构造函数和复制赋值运算符。
答案 2 :(得分:2)
在您的班级中拥有虚拟析构函数的唯一真正原因是,您是否计划删除该类多态的对象,即如果您计划通过delete
派生类的对象指向基类的指针。如果从不这样做,则不需要虚拟析构函数。
但是,如果你的类中已经有了一个虚函数,那么使析构函数虚拟化没有明显的开销(因为VMT指针已经被引入到你的对象中)。在这种情况下,将析构函数设置为虚拟可能是个好主意。以防万一。
答案 3 :(得分:1)
从技术上讲,只有在要进行多态删除实例时,必须才有虚拟析构函数。换句话说,您可以拥有虚拟方法而无需虚拟析构函数。
从实际的角度来看,很少有理由让你不要将析构函数声明为虚拟,并且应该为你认为可以用作基础的任何类完成它。
三条规则是讨论程序逻辑:如果你在任何析构函数,复制构造函数或赋值中都有逻辑,那么可能需要所有三个逻辑。但请注意,从正式的角度来看,它并不是一个严格的规则,并且在极少数情况下它根本不成立(例如,我可能有兴趣在日志中查看每个创建的对象的行,但不是在赋值时或破坏)。
另请注意,根据我的经验,当你有继承和多态时,C ++的复制语义甚至静态类型有时会感觉不对。
答案 4 :(得分:0)
任何可以作为基类的类都应该让它的析构函数声明为virtual。独立于另一个成员函数是否是虚拟的。
三条规则说你应该宣布一个
如果您声明其中一个。与破坏是否虚拟无关。