简体   繁体   English

删除基类中的复制和移动构造函数/赋值运算符就足够了吗?

[英]Is deleting copy and move constructors/assignment operators in base class enough?

If I have an abstract base class and I want to make all derived classes noncopyable and nonmovable is it sufficient to declare these special member functions deleted in the base class?如果我有一个抽象基类并且我想让所有派生类不可复制和不可移动,是否足以声明在基类中删除这些特殊成员函数? I want to ensure that my entire class hierarchy is noncopyable and nonmovable and am wondering if I can get away with not having to declare those 4 special member functions as deleted in every derived class.我想确保我的整个类层次结构是不可复制和不可移动的,我想知道我是否可以不必在每个派生类中将这 4 个特殊成员函数声明为已删除。 I saw a SO answer where it seemed to imply that a derived class could explicitly declare a copy or move constructor despite being deleted from the base class but the following example results in a compilation error when I try to define a defaulted copy assignment operator so I'm unsure.我看到了一个 SO 答案,其中似乎暗示派生类可以显式声明复制或移动构造函数,尽管已从基类中删除,但以下示例在我尝试定义默认复制赋值运算符时导致编译错误,因此我我不确定。 This is the error:这是错误:

derived_class.cc:15:15: error: defaulting this copy constructor would delete it after its first declaration DerivedClass::DerivedClass(const DerivedClass &) = default;派生类.cc:15:15:错误:默认此复制构造函数将在其第一次声明后删除它 DerivedClass::DerivedClass(const DerivedClass &) = default;

derived_class.h:9:22: note: copy constructor of 'DerivedClass' is implicitly deleted because base class 'virtual_functions::BaseClass' has a deleted copy constructor class DerivedClass : public BaseClass {派生类.h:9:22:注意:'DerivedClass'的复制构造函数被隐式删除,因为基类'virtual_functions::BaseClass'有一个删除的复制构造函数类DerivedClass:public BaseClass{

base_class.h:11:3: note: 'BaseClass' has been explicitly marked deleted here BaseClass(const BaseClass &) = delete; base_class.h:11:3: 注意: 'BaseClass' 在这里被明确标记为删除 BaseClass(const BaseClass &) = delete;

// base_class.h
class BaseClass {
public:
  BaseClass(const BaseClass &) = delete;
  BaseClass(BaseClass &&) = delete;
  BaseClass &operator=(const BaseClass &) = delete;
  BaseClass &operator=(BaseClass &&) = delete;
  virtual ~BaseClass() = default;
  virtual bool doSomething() = 0;

protected:
  BaseClass(std::string name);

private:
  std::string name_;
};

// derived_class.h
class DerivedClass : public BaseClass {
public:
  DerivedClass();
  DerivedClass(const DerivedClass &);
  bool doSomething() override;
};

// derived_class.cc
DerivedClass::DerivedClass(const DerivedClass &) = default;

You cannot prevent a child class from defining its own copy/move constructor.您不能阻止子类定义自己的复制/移动构造函数。 That said, it will prevent it "out of the box", meaning if you do not provide one, or use a inline default constructor, it will also be marked as deleted.也就是说,它会阻止它“开箱即用”,这意味着如果您不提供它,或者使用内联默认构造函数,它也会被标记为已删除。 The reason you get a error here when you try to just define the constructor as default is because you are not allowed to do that in an out of line definition when a member or base has implicitly deleted it.当您尝试仅将构造函数定义为默认值时,您在此处遇到错误的原因是,当成员或基类已隐式删除它时,不允许在行外定义中执行此操作。 Had you used你用过吗

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

then the code would compile, and you would only get an error if you actually try to call the copy constructor.然后代码会编译,如果你真的尝试调用复制构造函数,你只会得到一个错误。 This works because an inline implicit default is allowed even when a member or base implicitly deletes it and the end result is the constructor is implicitly deleted.这是有效的,因为即使成员或基隐式删除它并且最终结果是隐式删除构造函数时,也允许内联隐式默认值。

Is deleting copy and move constructors/assignment operators in base class enough?删除基类中的复制和移动构造函数/赋值运算符就足够了吗?

It is enough to prevent implicitly generated copy and move constructors/ assignment operators.这足以防止隐式生成的复制和移动构造函数/赋值运算符。

I saw a SO answer where it seemed to imply that a derived class could explicitly declare a copy or move constructor despite being deleted from the base class我看到了一个 SO 答案,其中似乎暗示派生类可以显式声明复制或移动构造函数,尽管已从基类中删除

This is correct.这是对的。 You cannot prevent this.你无法阻止这一点。 Well, you can prevent this by declaring the class final.好吧,您可以通过将类声明为 final 来防止这种情况发生。 Then there cannot be derived classes, and thus derived classes cannot be copyable.那么就不能有派生类,因此派生类不能被复制。

Of course, such explicitly declared copy constructor (and other) will not be able to copy the base sub object that is non-copyable.当然,这种显式声明的复制构造函数(和其他)将无法复制不可复制的基子对象。 The constructors must use BaseClass(std::string) and the assignment operators cannot modify the state of the base object in any way (unless they use some trick to get around access specifier encapsulation).构造函数必须使用BaseClass(std::string)并且赋值运算符不能以任何方式修改基对象的状态(除非它们使用一些技巧来绕过访问说明符封装)。

You cannot prevent a derived class to declare copy/move constructors, but they cannot be defaulted: the default copy ctor or a derived class would try to call the copy ctor of its base (same for move).您不能阻止派生类声明复制/移动构造函数,但它们不能被默认:默认复制构造函数或派生类会尝试调用其基类的复制构造函数(移动相同)。

But the derived class can explicitely construct its base with its default ctor:但是派生类可以使用其默认构造函数显式构造其基类:

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

Et voila... the class DerivedClass is now copyable despite its base class is not!瞧……类DerivedClass现在是可复制的,尽管它的基类不是!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 删除默认C ++复制和移动构造函数和赋值运算符的缺点? - Disadvantages to deleting default C++ copy and move constructors and assignment operators? 在将对象传递给函数的过程中删除了复制/移动构造函数和赋值运算符后,没有得到编译时错误 - Did not get a compile time error after deleting copy/move constructors and assignment operators during passing object to function 删除复制构造函数和复制赋值运算符。 哪一项至关重要? - Deleting copy constructors and copy assignment operators. Which of them are essential? 复制构造函数和赋值运算符 - Copy constructors and Assignment Operators 我们应该从派生类调用基类移动副本/赋值构造函数 - Should we be calling the base class move copy/assignment constructors from the derived class 继承并删除复制和移动构造方法 - Inheritance and deleting copy and move constructors 是否为派生类生成了移动构造函数/赋值运算符 - Are move constructors/assignment operators generated for derived classes 通过示例了解复制构造函数和赋值运算符 - Understanding copy constructors and assignment operators with an example 初始化器列表:复制构造函数和赋值运算符=冗余? - Initializer lists: copy constructors and assignment operators = redundancy? 我可以为一个类编写复制和移动赋值运算符吗? - Can I write both copy and move assignment operators for a class?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM