如何在不破坏移动和复制构造函数的情况下声明虚拟析构函数
Posted
技术标签:
【中文标题】如何在不破坏移动和复制构造函数的情况下声明虚拟析构函数【英文标题】:How to declare the virtual destructor without breaking move and copy constructors 【发布时间】:2016-05-09 17:33:29 【问题描述】:当向这样的类添加用户定义的默认虚拟析构函数时..
class Foo
public:
Foo();
virtual ~Foo() = default;
;
.. 它具有防止自动生成移动构造函数的副作用。也不推荐使用自动生成复制构造函数。 A recommended way is to user define all constructors 像这样..
class Foo
public:
Foo();
virtual ~Foo() = default;
Foo(const Foo& /* other */) = default;
Foo&operator=(const Foo& /* other */) = default;
Foo(Foo&& /* other */) = default;
Foo&operator=(Foo&& /* other */) = default;
;
但是,这非常冗长且难以阅读。有没有其他解决方案?
【问题讨论】:
如果您有一个虚拟 dtor,您可能希望删除所有复制和移动 ctor。 并且可能有一个clone()
方法来代替。
我认为您希望所有类中的最后四行无论如何(可能使用= delete
而不是= default
) - 只是为了清楚类正在提供。 (可以说,如果你删除了“复制”功能,则无需提及“移动”功能。)
@MartinBonner 我认为所有最后的五行都应该避免如果可能的话。通过 raii 设计,这几乎总是可能的。到处复制五行样板代码并不能增加清晰度。但是,如果您添加一个,则添加其余的!
【参考方案1】:
首先我会考虑Foo
是否真的需要一个虚拟析构函数。也许您可以使用简单的模板以类型安全的方式解决您的问题,从而避免弄乱指针和强制转换等。
如果您决定将Foo
设为虚拟,那么我会推荐这种抽象。
class VirtualDestructor
protected:
VirtualDestructor() = default;
virtual ~VirtualDestructor() = default;
VirtualDestructor(const VirtualDestructor & /* other */) = default;
VirtualDestructor &operator=(const VirtualDestructor & /* other */) = default;
VirtualDestructor(VirtualDestructor && /* other */) = default;
VirtualDestructor &operator=(VirtualDestructor && /* other */) = default;
;
将其放入适当的namespace
的库中。然后你可以保持Foo
和所有其他虚拟类干净。
class Foo : VirtualDestructor
public:
Foo();
;
删除复制构造函数时也可以使用相同的技术。
编辑: Compiler output 和 diff with original code
【讨论】:
您能否详细说明Foo
直接在其中包含这些= default
定义时的行为以及从VirtualDestructor
继承它们时的行为的差异(如果有)?跨度>
@einpoklum 用两个版本的编译器输出更新了答案。
虚拟析构函数不会抑制operator=
,所以我建议从你的类中删除它们(你的选择对派生类施加了条件,例如他们可能想要使用复制和交换)
以上是关于如何在不破坏移动和复制构造函数的情况下声明虚拟析构函数的主要内容,如果未能解决你的问题,请参考以下文章