通过在基类中声明复制构造函数/运算符private,可以使派生类不可复制吗?

时间:2015-07-08 09:57:27

标签: c++ abstract-class private copy-constructor base-class

我在理论上认为这个问题的答案是肯定的。

然而,在实践中,我的编译器(VS2010)似乎并没有在以下情况下抱怨:我有一个抽象基类提供了一些通用接口(但没有数据成员)以及从中派生的各种子类和子类。 / p>

class Base 
{
public:
    Base() {}
    virtual ~Base() {}

    virtual void interfaceFunction1() = 0;
    virtual void interfaceFunction2() = 0;
private:
    Base(const Base&);            // all derived classes should be uncopyable
    Base& operator=(const Base&);

    // no data members
};

我的编译器发现甚至在子子类或子子类中实现完整拷贝构造函数也没有问题。

如何确保从Base派生的每个类都是不可复制的?

编辑如果我理解得很好,这正是Scott Meyers在Effective C ++(第3版,2005)第6项中解释的,他对类Uncopyable的想法(仅扩展)这里是一个完整的接口类)。是什么让他的想法发挥作用? (我知道他私下继承,但这不应该造成问题)

3 个答案:

答案 0 :(得分:3)

这应该可以防止编译器为派生类生成一个复制构造函数,而不会显式声明一个派生类。但是,没有什么可以阻止派生类显式声明一个复制构造函数,它将执行除Base的复制构造函数之外的其他操作。

无法确保派生类是可实例化的,但不可复制。

答案 1 :(得分:1)

而不是将复制构造函数/运算符声明为 private ,而不是将它们声明为已删除。将复制构造函数/运算符声明为私有不是使派生类不可复制的最佳解决方案。如果您希望基类完全不可复制,则将复制构造函数/运算符声明为 delete d,因为复制仍然可以在 Base 的成员函数中作为私有进行成员可以访问该类的功能。您可以使用delete的C ++ 11功能:

Base(const Base&) = delete; // copy constructor
Base& operator=(const Base&) = delete; // copy-assignment operator

但是,只要你知道副本仍然可以在 Base 的成员函数中发生,那么将复制构造函数/运算符声明为 private 也是正确的。

答案 2 :(得分:0)

在C ++ 11和更高版本中,可以选择声明已删除的构造函数。

struct X {
  X( const X& ) = delete;
};

现在,任何从X派生而依赖于复制构造函数的东西都将无法编译。 当您想避免问题时,此功能非常有用,因为编译器会自动生成构造函数...