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



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

然而,在实践中,我的编译器(VS2010)似乎没有在以下情况下抱怨:我有一个抽象基类提供一些公共接口(但没有数据成员)和各种子和子子类派生自它。

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是不可复制的?

edit:如果我理解得好,这正是Scott Meyers在Effective c++(2005年第3版)的第6项中对Uncopyable类(仅在这里扩展为完整的接口类)的想法所解释的。是什么让他的想法行得通呢?(我知道他是私下继承的,但这应该不成问题)

这将防止编译器为未显式声明的派生类生成复制构造函数。但是,没有什么可以阻止派生类显式声明复制构造函数,该构造函数将做一些其他事情,而不是调用Base的复制构造函数。

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

与其将复制构造函数/操作符声明为private,不如声明为已删除。将复制构造函数/操作符声明为private并不是使派生类不可复制的最佳解决方案。如果您希望基类完全不可复制,则将复制构造函数/操作符声明为deleted,因为复制仍然可以在 base 的成员函数内部进行,因为该类函数可以访问私有成员。你可以使用c++ 11的delete特性:

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

但是将复制构造函数/操作符声明为private也是正确的,只要您意识到复制仍然可以在Base的成员函数中进行。

在c++ 11及以后的版本中,有声明已删除构造函数的选项。

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

现在,任何从X派生的依赖复制构造函数的东西都不能编译。当你想避免问题,因为编译器会自动生成构造函数时,这是非常有用的…

最新更新