C++虚拟操作符delete?

18

是否可以拥有虚拟的删除运算符?我不是在谈论析构函数,我指的是实际的运算符重载。

尽管在大多数情况下重载new和delete是一个很糟糕的想法(是的,我已经知道这是异端邪说),但我想知道使用虚拟删除运算符会有什么样的影响。

我想尝试使用虚拟删除,因为有时候我可能会有一个重载了delete的子类存储在基类指针中。从技术上讲,我并没有真正预见到这种情况会带来太多的成果,除非我有一棵不同节点类型的树(如果你问我的话,这本身就是一个潜在的危险想法)。

我只想知道虚拟或非虚拟删除运算符覆盖的潜在优缺点是什么。


1
您可以通过编译器大约30秒的时间来自己回答第一个问题。 - user207421
@EJP 确实。我有一个设置,可以测试它。等一下。 - Serge
是的...谢谢大家的澄清。愚蠢的问题就是愚蠢!=) - Serge
3
好问题,点个赞。嘿嘿。 - Cheers and hth. - Alf
3个回答

19
您不能将operator delete明确声明为virtual。即使不提供关键字static,它也是一个静态成员函数。operator delete在最终派生类中定义的版本会被使用,因此可以认为它是由析构函数调用的,甚至可能确实如此。C++11 §12.4/12规定:在虚析构函数(包括隐式定义的虚析构函数)的定义点上,在析构函数所在类的作用域中查找非数组释放函数。如果没有找到声明,则在全局作用域中查找。C++11 §12.5/4规定:如果delete-expression以一元::运算符开头,则在全局作用域中查找解除分配函数的名称。否则,如果delete-expression用于解除分配具有虚析构函数的静态类型的类对象,则在动态类型的虚拟析构函数的定义点选择解除分配函数。否则,如果delete-expression用于解除分配类T或其数组的对象,则该对象的静态类型和动态类型必须相同,并且在T的作用域中查找解除分配函数的名称。如果这个查找未能找到名称,则在全局作用域中查找。如果查找结果不明确或不可访问,或者如果查找选择了放置解除分配函数,则程序是非法的。

1
所以,简单来说,如果一个对象有一个虚拟~destructor(),它将使用关联的delete重载?知道这点很好... =) - Serge
2
@Serge:避免使用最派生类的解分配函数的唯一方法,就是引入一些未定义行为(例如,通过基类指针删除并且没有虚析构函数)。 - Cheers and hth. - Alf
2
这为我提供了一种保证调用适当的删除重载的方法。我所要做的就是提供一个虚拟析构函数的虚拟实现。 - Serge

7
即使你不将其标记为虚函数,当/如果你重载一个类的new/delete时,它们最终变成静态成员函数1,而静态成员函数不能是虚函数。
为了正常工作,它们确实需要是静态的——它们用于分配/释放对象的内存,因此必须在对象开始构造之前/完成销毁之后发生。显然,你不能让它为最终会成为类实例的对象分配内存,并且同时让它依赖于已经存在的类实例(这是虚函数所做的)。
  1. §12.5/1:

任何类T的分配函数都是静态成员(即使没有明确声明为静态成员)。

和 §12.5/6:

任何类X的拨款函数都是静态成员(即使没有明确声明为静态成员)。

…对于那些关心官方声明的人来说,这很有趣。有趣的是当你分配时它是一个“类T”,而当你释放时它是一个“类X”。


4
不行-你不能拥有虚拟操作符删除-类特定的new和delete重载必须是静态成员函数-特定于类而不是对象。 你不能拥有虚拟静态成员函数。 见标准的12.5.7节,它指出“由于成员分配和释放函数是静态的,因此它们不能是虚拟的”。

谢谢,我没有意识到它们是静态的。主要是因为我没有声明它们为静态的。 - Serge

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