C++ 如何在不中断move和copy构造函数的情况下声明虚拟析构函数

C++ 如何在不中断move和copy构造函数的情况下声明虚拟析构函数,c++,c++11,virtual-destructor,C++,C++11,Virtual Destructor,将用户定义的默认虚拟析构函数添加到这样的类时 class Foo { public: Foo(); virtual ~Foo() = default; }; class Foo { public: Foo(); virtual ~Foo() = default; Foo(const Foo& /* other */) = default; Foo&operator=(const Foo& /* other */) = default;

将用户定义的默认虚拟析构函数添加到这样的类时

class Foo
{
public:
    Foo();
    virtual ~Foo() = default;
};
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;
};
。。它的副作用是防止自动生成移动构造函数。此外,不推荐自动生成副本构造函数。像这样

class Foo
{
public:
    Foo();
    virtual ~Foo() = default;
};
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;
};

然而,这是超级冗长和不可读的。还有其他的解决方案吗?

首先,我会考虑<代码> 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;
};
将其放入适当的
命名空间中的库中。然后可以保持
Foo
和所有其他虚拟类的干净

class Foo : VirtualDestructor
{
public:
    Foo();
};
例如,在删除复制构造函数时,也可以使用相同的技术

编辑:
以及

如果直接在
=default
定义中包含这些定义,您能否详细说明
Foo
行为的差异(如果有),以及它从
VirtualDestructor
继承它们时的行为?@einpoklum使用两个版本的编译器输出更新了答案。虚拟析构函数不会抑制
运算符=
,因此我建议从类中删除它们(您的选择对派生类施加了一个条件,例如,它们可能想要使用复制和交换)如果您有一个虚拟dtor,您可能无论如何都想删除所有复制和移动CTOR。并且可能会有一个
clone()
方法。我认为您无论如何都想要所有类中的最后四行(可能使用
=delete
而不是
=default
)-只是为了明确类提供了什么。(如果删除了“复制”函数,则不需要提及“移动”函数。)@MartinBonner我认为,如果可能的话,最后五行都应该避免。根据raii设计,这几乎总是可能的。到处复制五行样板文件不会增加清晰度。但是如果你添加一行,那么就添加其余的!