无法在析构函数中使用虚拟关键字

3

是否存在任何有效和可用的情况,会迫使您在析构函数之前不使用虚拟关键字。

class Base {
public:
  virtual ~Base() { ... } // `virtual` causes error (not compile time or syntax) or wrong behaviour
  // could contain other fields

};

// some example 

3
当需要时使用"virtual",不需要时则不要使用。我不理解。 - L. F.
你遇到了什么问题?也许直接询问会更好? - Some programmer dude
如果我理解正确,这个问题的相反是:“什么时候使用虚析构函数?” - Evg
我的意思是一种情况,你将被迫从析构函数中删除 virtual。它不会产生任何编译器/语法错误,但会导致错误的行为。 - arsdever
“错误行为”也是您可以在此询问的内容。创建一个[mcve]来复制“错误行为”,并发布一个新问题。 - Some programmer dude
如果基类不打算用作销毁派生类的方式,那么应该使用非虚拟受保护的析构函数。(其他语言可能将这些类称为“接口”,但C++在核心语言中不区分两者。) - Eljay
2个回答

6

将析构函数定义为virtual有可能将您的class从非多态类型转换为多态类型。

请注意,多态类型永远不是平凡可复制的(trivially copyable)。例如,引入虚拟析构函数可能会破坏对std::memcpy的任何使用。

在某些情况下,特别是与C进行交互时,这可能会造成混乱,因为您不能再假设实例的地址与第一个成员的地址相同。

参考:https://en.cppreference.com/w/cpp/types/is_trivially_copyable


你的意思是问题不在于析构函数的虚拟性,而是虚拟性本身。我说得对吗? - arsdever
1
@arsdever:是的。如果你的类型还不是虚拟的,析构函数就是它变成虚拟的手段。 - Bathsheba

3
是否有任何有效可用的情况,强制您在析构函数之前不使用虚关键字?
是的。如果您曾经使用过std::memcpystd::memcmp与类的实例或其成员,或者依赖于指向/来自实例的指针可以转换为该类的第一个成员,或者检查该类类型的非活动联合成员的公共初始序列。
总的来说:如果您依赖于该类是标准布局类型或平凡可复制的,则析构函数(以及所有其他成员函数)必须是非虚拟的。大多数错误地假设标准布局或平凡性的情况都具有未定义行为。这些属性可以通过类型特征和静态断言强制执行,以便您得到一个很好的编译错误。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接