2016-08-15 68 views
2

我我的C期间,在2个愚蠢的问题绊倒++ practixe:如何提高::不可复制工作

  1. 在C++ AFAIK拷贝构造函数和赋值操作符是不可继承......所以如何提高::在这种情况下禁止这种东西的不可复制的帮助?

     
    class X: private boost::noncopyable 
    { 
    }; 
    
    是否有必要仅使用私有继承来实现目标?

  2. 是否只有一种方法来声明赋值运算符

     
    MyClass& operator= (const MyClass &); 
    
    声明
     
    void operator= (const MyClass &);
     
    const MyClass& operator= (const MyClass &);
    是否是一样的东西?

+2

它们不是继承的。但编译器生成的调用所有的基类复制c'tors ... – StoryTeller

+0

它不必私下继承,但这样做可以防止愚蠢的代码,如'boost :: noncopyable const&x = X {};' – Praetorian

回答

2

在C++ 11及更高版本中的不可复制将通过声明它为=delete,最好是公共的。然而,在C++ 11,这是不可能的,2个技术组合使用:

  • 声明私有方法
  • 没有实现方法

通过制作方法私人,这不能被非朋友类调用。因此,任何试图调用此代码的代码都会导致编译错误。

实际上,班级仍然可以自我复制。因此这个方法没有得到实现,你会得到一个链接器错误。

boost::noncopyable继承将阻止第二个用例,但是,它也可以防止编译器可以生成有效的默认拷贝构造函数...因为它们将违反先前的约束。

请注意,如果您确实需要,可以通过调用这些“不可复制”类的普通构造函数来为继承类编写复制构造函数。

对于第二个问题:是的,你可以给它任何你想要的返回类型,尽管你不能再写a = b = c;

+1

@Quentin Tnx,那就是我的意思! – JVApen

+0

谢谢,这是对我的完整解释! – Dmitry

0

1)当构造对象时,还必须构造所有成员对象和基础对象。由于noncopyable::noncopyable(const noncopyable &)是私人的,因此noncopyable不能被复制。因此,包含它作为成员或基地的任何对象也不能被复制构建。

2)您可以将您描述的三种方法中的任何一种声明为您的赋值操作符。不,他们不是“同一件事”。一个返回一个可变引用,一个返回一个const引用,另一个返回void。如果您尝试对赋值运算符的结果进行操作,则区别将会很明显。考虑这个程序片段:

a = b; 
(a = b).foo() 

第一行将与您的任何赋值操作符一样操作。第二行将根据您使用的赋值运算符而有所不同。

+1

[ 'boost :: noncopyable'](http://www.boost.org/doc/libs/1_55_0/boost/noncopyable.hpp)是可以构造的。 – NathanOliver

+1

我不认为'boost :: noncopyable :: noncopyable()'是私有的。 – aschepler

+0

它不能是私有的,因为那意味着你不能构建你的初始实例。 – JVApen

1

复制构造函数和复制赋值运算符没有被继承是正确的。幸运的是,我们并不需要它们继承以使其发挥作用。如果你从一个不能被复制的类继承,那么这个派生类不能被复制,也不能在它的拷贝构造函数中调用基类拷贝构造函数。

基本你从一个类继承看起来像

struct NonCopyable { 
    NonCopyable & operator=(const NonCopyable&) = delete; 
    NonCopyable(const NonCopyable&) = delete; 
    NonCopyable() = default; 
}; 

这足以停止工作在派生类中的编译器生成的拷贝和赋值。你可以提供你自己的并且覆盖这个,但是那就是击败了这一点。