c ++中私有拷贝构造函数的用法是什么?

为什么人们定义一个私人拷贝构造函数?

何时使复制构造函数和赋值运算符私有一个好的devise?

如果在类中没有成员是指向唯一对象(如文件名)的指针或句柄,那么其他情况下,私有拷贝构造函数是一个好主意?

同样的问题适用于赋值运算符。 考虑到大多数C ++围绕着对象的复制和引用而传递,有没有涉及私有拷贝构造函数的好devise?

一些对象表示不能或不应该被复制的特定实体。 例如,可以防止代表应用程序使用的日志文件的对象的复制,这对应于单个日志文件将被代码的所有部分使用的期望。 使用意外或不适当的复制对象可能导致乱序内容出现在日志中,当前日志大小不准确的logging,多次尝试(一些失败)“滚动”到新的日志文件名或重命名现有的日志文件。

另一个用途是通过虚拟function强制执行复制。 由于构造函数不能是virtual ,通常的做法是防止直接访问复制构造函数,并提供一个virtual Base* clone()方法,返回一个指针所指向的实际运行时types的副本。 这可以防止Base b(derived)将出现的意外切片。

另一个例子:一个简单的智能指针对象,它简单地删除它在构造函数中给出的指针:如果它不支持引用计数或其他一些处理多个所有者的方法,并且不想冒有意外的风险std::auto_ptr风格的所有权转移,然后简单地隐藏复制构造函数给出一个伟大的小智能指针,它是快速和有效的有限的情况下,它是可用的。 关于试图复制它的编译时错误会有效地要求程序员“嘿,如果你真的想这样做,那么改变我的共享指针,否则退出!”

一个用例是单个模式 ,其中只能有一个类的实例 。 在这种情况下,您需要使您的构造函数和赋值operator = private,以便无法创build多个对象。 创build对象的唯一方法是通过GetInstance()函数,如下所示。

 // An example of singleton pattern class CMySingleton { public: static CMySingleton& GetInstance() { static CMySingleton singleton; return singleton; } // Other non-static member functions private: CMySingleton() {} // Private constructor ~CMySingleton() {} CMySingleton(const CMySingleton&); // Prevent copy-construction CMySingleton& operator=(const CMySingleton&); // Prevent assignment }; int main(int argc, char* argv[]) { // create a single instance of the class CMySingleton &object = CMySingleton::GetInstance(); // compile fail due to private constructor CMySingleton object1; // compile fail due to private copy constructor CMySingleton object2(object); // compile fail due to private assignment operator object1 = object; // .. return 0; } 

一个非常糟糕的例子:

 class Vehicle : { int wheels; Vehicle(int w) : wheels(w) {} } class Car : public Vehicle { Engine * engine; public Car(Engine * e) : Vehicle(4), engine(e) } ... Car c(new Engine()); Car c2(c); // Now both cars share the same engine! Vehicle v; v = c; // This doesn't even make any sense; all you have is a Vehicle with 4 wheels but no engine. 

这是什么意思,“复制”一辆车? (汽车是汽车模型还是汽车实例?是否复制它保存车辆注册?)

将车辆分配给另一辆车意味着什么?

如果这些操作是没有意义的(或者仅仅是未实现的),那么标准的做法是使拷贝构造函数和赋值运算符是私有的,如果它们被使用而不是奇怪的行为会导致编译错误。

复制构造函数和复制赋值私有的一个常见原因是禁用这些操作的默认实现。 但是,在C ++ 0x中有这样的特殊语法= 删除 。 所以在C ++ 0x使抄送ctor私人似乎被resrtricted非常奇特的情况下。

复制ctors和任务是相当的句法糖; 所以这样的“私人糖”似乎是贪婪的症状:)

即使对象的内容不是指针或其他引用,但是防止人们复制对象仍然是有用的。 也许这个类包含了大量的数据,而且复制操作太重了。

“ 虚拟构造函数成语 ”是需要私有或受保护的拷贝构造函数的重要情况。 在C ++中出现了一个问题,在这里给出了一个指向基类的指针,一个实际上是从这个基类inheritance的对象,并且你想把它复制一份。 调用复制构造函数不会调用inheritance类的复制构造函数,而是实际调用基类的复制构造函数。

注意:

 class Base { public: Base( const Base & ref ){ std::cout << "Base copy constructor" ; } }; class Derived : public Base { public: Derived( const Derived & ref ) : Base(ref) { std::cout << "Derived copy constructor"; } } Base * obj = new Derived; Base * obj2 = new Derived(*obj); 

上面的代码会产生输出:

 "Base copy constructor" 

这显然不是程序员想要的行为! 程序员试图复制一个“派生”types的对象,而是取回一个types为“Base”的对象!

这个问题是通过使用上述习语来纠正的。 观察上面写的例子,重写成使用这个习语:

 class Base { public: virtual Base * clone () const = 0; //this will need to be implemented by derived class protected: Base( const Base & ref ){ std::cout << "Base copy constructor" ; } }; class Derived : public Base { public: virtual Base * clone () const { //call private copy constructor of class "Derived" return static_cast<Base *>( new Derived(*this) ); } //private copy constructor: private: Derived( const Derived & ref ) : Base(ref) { std::cout << "Derived copy constructor"; } } Base * obj = new Derived; Base * obj2 = obj->clone(); 

上面的代码将产生输出:

 "Base copy constructor" "Derived copy constructor" 

换句话说,构造了所需types“派生”的对象,而不是“基础”types的对象!

正如你所看到的,在Derivedtypes中,拷贝构造函数被故意设置为私有的,因为这样做会让程序员不小心尝试手动调用拷贝构造函数,而不是使用clone提供的巧妙接口)。 换句话说,可用的可直接调用的公共拷贝构造函数可能会导致程序员犯第1部分中提到的错误。在这种情况下,最佳做法是将拷贝构造函数从视图中隐藏起来,并且只能通过使用“clone )”。

您可能想要使用复制构造函数来实现类的某些方法,但不要在类之外公开它。 那么你把它变成私人的 像任何其他方法一样。