2011-07-25 6 views
7

Lấy cảm hứng từ this question.Tại sao tôi phải tạo bản sao của nhà xây dựng và toán tử gán riêng và được triển khai trong C++?

Thông thường lý do để làm cho nhà tạo bản sao và nhà điều hành gán privatemake the class non-copyable để các đối tượng chỉ có thể được tạo và hủy, nhưng không được sao chép - phần lớn thời gian là vì sao chép chúng sẽ không có ý nghĩa. Trong những trường hợp như vậy, hàm tạo bản sao và toán tử gán đều được thực hiện privatevà không được triển khai - nếu lớp đó không thể sao chép được thì không ai nên sao chép.

Có trường hợp nào khi người tạo bản sao và nhà điều hành chuyển nhượng cần phải là private và thực hiện có ý nghĩa cùng một lúc?

+0

đọc các chức năng đã xóa của C++ 0x, là cú pháp đường cho loại điều này bằng cách sử dụng '= delete' thay vì nhảy qua các vòng lặp. – rubenvb

+1

Làm thế nào đây không phải là một sự lừa dối của câu hỏi khác? Cái kia không chỉ định * chỉ * các hàm tạo riêng với các hiện thực, nhưng ít nhất một câu trả lời (http://stackoverflow.com/questions/6811037/whats-the-use-of-the-private-copy-constructor-in- c/6811507 # 6811507) liên quan đến điều đó. –

+0

@Steve Jessop: Vấn đề là lý do số một để họ có riêng tư là ngăn chặn sao chép hoàn toàn và sau đó họ không được thực hiện và đó là điều mà hầu hết mọi người (tôi cũng nghĩ) khi họ được hỏi về điều này. Vì tôi đặc biệt quan tâm đến kịch bản "riêng tư + được triển khai", tôi phải đặt câu hỏi này và nhấn mạnh cụ thể. – sharptooth

Trả lời

7

Có hai trường hợp mà tôi suy nghĩ ngay lập tức:

  1. friend s:

    Say rằng, như là một phần của thiết kế, bạn có hai lớp kết hợp cao, nơi bạn có thể sao chép các lớp khác (ví dụ như trong mô hình nhà máy hoặc một số kiểu như vậy), nhưng bạn không muốn để cả thế giới có thể để sao chép nó.

  2. wrappers:

    Giả sử bạn muốn để có thể có điều kiện sao chép một số yếu tố, tùy thuộc vào một số hành vi nội bộ (ví dụ, tùy thuộc vào một số điều kiện đẳng cấp stateful) - cách sạch nhất, từ góc độ ngôn ngữ - là vẫn để tách bản sao chép thành chức năng riêng của nó. Điều này sẽ cho phép phân tách mối quan tâm tốt.

+0

+1, câu trả lời của chúng tôi rất giống nhau. :) – iammilind

7

Tôi đoán là điều này có thể hữu ích cho một lớp đang giữ danh sách chính nó - sau đó nó có thể sao chép các phiên bản nội bộ. Điều này thực sự chỉ hữu ích cho một lớp có cả mục và vùng chứa:

class MyItems 
{ 
private: 
    /* Copy ctor and =operator */ 
    List list; 
public: 
    void AddItems(MyItems* items) 
    { 
     MyItems* added = new MyItems(items); 
     list.Add(added); 
    } 
}; 

Một suy nghĩ khác là cho phép nhân bản trong hoàn cảnh do lớp kiểm soát. Điều này có thể hữu ích khi sao chép có thể có ý nghĩa, nhưng chỉ về điều kiện hoặc điều khoản cụ thể:

class MyClass 
{ 
private: 
    /* Copy ctor and =operator */ 
public: 
    MyClass* clone() 
    { 
     if (canClone) 
     { 
      MyClass* cloned = new MyClass(this); 
      return cloned; 
     } 
     else 
     { 
      return NULL; 
     } 
    } 
}; 
+1

Tại sao bạn muốn cấm khách hàng tạo bản sao trong ví dụ đầu tiên? –

+1

@Martinho: Đối tượng 'List' có thể không sở hữu với' List :: add'. Do đó, việc giữ cho các máy khách tạo các bản sao trong ví dụ đầu tiên giúp bạn không phải lo lắng về việc ai sở hữu các cá thể 'MyItem' trong thành viên' list'. –

5
  1. Chúng tôi làm sao xây dựng và operator = chưa thực hiện vì vậy mà ngay một friend không thể có bất kỳ truy cập vào nó. Nếu bạn triển khai, điều đó có nghĩa là bạn muốn có một số friend để có quyền truy cập. Đây là một quyết định thiết kế.
  2. Bạn muốn làm nhân bản rõ ràng; ví dụ: cho phép sao chép mà còn làm cho mã của nó "bẩn" tìm kiếm (giống như C++ phong cách đúc hoạt động, trong đó cho thấy dirt in your code)

ví dụ

class A { 
    A(const A& obj) { ... } 
    A& operator = (const A& obj) { ... } 
public: 
    A& clone(const A& obj) 
    { 
    *this = obj; 
    return *this; 
    } 
}; 

Chúng tôi đã đặt trình bao bọc này clone() để cho phép người dùng nhân bản, tuy nhiên nó cũng hiển thị chính xác những gì chính xác người đó đang làm.