C++ 删除基类中的复制和移动构造函数/赋值运算符是否足够?

C++ 删除基类中的复制和移动构造函数/赋值运算符是否足够?,c++,c++11,deleted-functions,C++,C++11,Deleted Functions,如果我有一个抽象基类,并且我想使所有派生类都不可复制和不可移动,那么声明这些特殊的成员函数在基类中被删除就足够了吗?我想确保我的整个类层次结构是不可复制和不可更改的,我想知道我是否可以不必在每个派生类中将这4个特殊成员函数声明为已删除。我看到了这样一个答案,它似乎暗示派生类可以显式声明一个复制或移动构造函数,尽管从基类中删除了它,但下面的示例在我尝试定义默认的复制赋值运算符时导致编译错误,因此我不确定。这就是错误: 派生类。cc:15:15:错误:默认此副本构造函数将在其第一次声明后删除它 De

如果我有一个抽象基类,并且我想使所有派生类都不可复制和不可移动,那么声明这些特殊的成员函数在基类中被删除就足够了吗?我想确保我的整个类层次结构是不可复制和不可更改的,我想知道我是否可以不必在每个派生类中将这4个特殊成员函数声明为已删除。我看到了这样一个答案,它似乎暗示派生类可以显式声明一个复制或移动构造函数,尽管从基类中删除了它,但下面的示例在我尝试定义默认的复制赋值运算符时导致编译错误,因此我不确定。这就是错误:

派生类。cc:15:15:错误:默认此副本构造函数将在其第一次声明后删除它 DerivedClass::DerivedClass(const-DerivedClass&)=默认值

派生类。h:9:22:注意:“DerivedClass”的复制构造函数被隐式删除,因为基类“virtual_functions::BaseClass”有一个已删除的复制构造函数 类派生类:公共基类{

基类。h:11:3:注意:“基类”已在此处显式标记为“已删除” 基类(常量基类&)=删除

删除基类中的复制和移动构造函数/赋值运算符是否足够

这足以防止隐式生成复制和移动构造函数/赋值运算符

我看到了这样一个答案,它似乎意味着派生类可以显式声明一个复制或移动构造函数,尽管从基类中删除了它

这是正确的。您无法阻止这一点。您可以通过声明类final来防止这一点。这样就不存在派生类,因此派生类不可复制


当然,这种显式声明的复制构造函数(和其他)将无法复制不可复制的基子对象。构造函数必须使用
BaseClass(std::string)
,赋值运算符不能以任何方式修改基对象的状态(除非他们使用一些技巧绕过访问说明符封装)。

您不能阻止子类定义自己的复制/移动构造函数。也就是说,它将阻止它“开箱即用”,这意味着如果您不提供或使用内联默认构造函数,它也将被标记为已删除。当您尝试仅将构造函数定义为默认构造函数时,出现错误的原因是,当成员或基隐式删除它时,不允许在越界定义中执行此操作。是否使用了

class DerivedClass : public BaseClass {
public:
  DerivedClass(const DerivedClass &) = default;
  bool doSomething() override;
};

然后代码将被编译,只有在实际尝试调用复制构造函数时才会出现错误。这是因为即使成员或基隐式删除它,也允许使用内联隐式默认值,并且最终结果是隐式删除了构造函数。

无法阻止派生类声明复制/移动常量构造函数,但它们不能是默认的:默认的复制构造函数或派生类将尝试调用其基的复制构造函数(对于move也一样)

但是派生类可以使用其默认的构造函数显式地构造其基:

class DerivedClass : public BaseClass {
public:
  DerivedClass();
  DerivedClass(const DerivedClass &): BaseClass() {
      // copy ctor for the derived part
  }
  bool doSomething() override;
};

等等,瞧……类
派生类
现在是可复制的,尽管它的基类是不可复制的!

我遵循了这个指导,这就是为什么我在第一次声明之后使用了
=default
,在这种情况下它似乎工作得很好。如果我像您那样在第一次声明中添加
=default
,那么编译成功了eds,如您所述,但复制构造函数并未实际生成。当您尝试将构造函数定义为默认值时,此处出现错误的原因是,在越界定义中不允许这样做。我觉得上面的语句不太正确。这是允许的,但在这种情况下不允许。@MikeSweeney我已更新了措辞使之更明确。谢谢。我重新阅读了你的原始答案几次,你的观点是正确的,但我认为对于大多数提出这个问题的人来说,这太微妙了,难以理解。现在回答得很好。@MikeSweeney谢谢。很高兴能帮上忙。如果基类是可复制的,并且我想定义我自己的
DerivedClass
copy constructor在这样做时,我将如何调用
BaseClass
copy构造函数?@MikeSweeney如果基类是可复制的,那么语法是
Derived(Derived const&other):base(other),任何其他驱动成员{body}
class DerivedClass : public BaseClass {
public:
  DerivedClass();
  DerivedClass(const DerivedClass &): BaseClass() {
      // copy ctor for the derived part
  }
  bool doSomething() override;
};