2013-05-26 40 views
14

Ví dụ: tôi muốn khai báo lớp nhưng tôi muốn khách hàng không thể sử dụng hàm tạo bản sao (hoặc sao chép toán tử gán)Sự khác biệt giữa khai báo một hàm tạo riêng và = delete là gì?

Cả hai điều sau đây đều không cho phép sử dụng hàm tạo bản sao:

1.

class Track 
{ 
public: 
    Track(){}; 
    ~Track(){}; 
private: 
    Track(const Track&){}; 
}; 

2.

class Track 
{ 
public: 
    Track(){}; 
    ~Track(){}; 
    Track(const Track&)=delete; 
}; 

Một trong những cách này "chính xác hơn" khác hay bằng nhau? Có tác dụng phụ nào không?

//Does not compile with both the above ways 
int main() 
{ 
    Track l; 
    Track p(l); 
} 
+0

Điều này có biên dịch 'Track (const Track &) = delete;' ??? –

+1

@EdHeal có, nó có. g ++ 4.7 –

+0

Không thấy việc sử dụng 'xóa' trước đó. Tiện ích mở rộng ngôn ngữ? Nếu có, thì điều đầu tiên chắc chắn là "chính xác hơn" – kotlomoy

Trả lời

15

Đặt chế độ riêng tư là cách "cũ". Hàm khởi tạo vẫn tồn tại, nhưng nó là riêng tư và chỉ có thể được gọi từ bên trong một hàm thành viên lớp khác.

= deletexóa hàm tạo. Nó không được tạo ra bởi trình biên dịch, và nó đơn giản sẽ không tồn tại.

Rất có thể, = delete là những gì bạn muốn. (mặc dù với báo trước rằng không phải tất cả các trình biên dịch đều hỗ trợ cú pháp này, vì vậy nếu tính di động là một mối quan tâm ...)

6

Tuyên bố một constructor sao chép private vẫn cho phép các hàm thành viên của lớp Track để sao chép-xây dựng trường của lớp đó, trong khi làm cho nó bị xóa chỉ đơn giản là cấm sao chép xây dựng đối tượng đó.

Trong C++ 11, xóa một constructor sao chép là đúng cách để bày tỏ một thực tế rằng một lớp là không copyable (tất nhiên trừ khi nó có ý nghĩa đối với bạn để cho hàm thành viên của Track, hoặc bạn bè của Track, để sao chép-xây dựng Track đối tượng).

5

Làm cho một nhà xây dựng riêng về cơ bản là "hack" trong C++ cũ, vì đó là cách duy nhất để ngăn người dùng sử dụng chúng. Khả năng delete chức năng thành viên đặc biệt chỉ được giới thiệu trong C++ 11, và đó là cách tốt hơn và thành ngữ hơn để nói rằng một lớp không thể được sao chép. vì nó rõ ràng về ý định .

Các nhà thầu tư nhân có các công dụng khác ngoài việc cấm sử dụng hoàn toàn (ví dụ: chúng có thể được gọi bởi các hàm thành viên lớp tĩnh). Vì vậy, việc tạo một hàm tạo riêng tư không truyền đạt ý định rất tốt, và lỗi kết quả cũng không rõ ràng lắm.

0

Cách tiếp cận đầu tiên của bạn không ngăn chính lớp sao chép chính nó. Cách truyền thống để giải quyết điều này là tuyên bố bản sao-constructor riêng để nó không được thực hiện.

Một vấn đề với điều đó, tuy nhiên, đó là ý định có thể không rõ ràng. Ai đó đọc mã có thể không hiểu tại sao một tờ khai mồ côi tồn tại và có thể xóa nhầm nó. Nhận xét có thể trợ giúp, như sẽ kế thừa riêng tư từ boost::noncopyable nếu Tăng khả dụng cho bạn.

Cách tiếp cận thứ hai làm cho mục đích rõ ràng và là những gì bạn nên thích nếu bạn có thể sử dụng C++ 11.

0

Giải pháp đầu tiên của bạn truyền đạt cho người đọc rằng trình tạo bản sao là riêng tư và không được sử dụng. Giải pháp thứ hai của bạn chỉ hợp lệ trong C++ 11. Bởi vì điều này, tôi muốn nói việc thực hiện di động và dễ đọc hơn sẽ là việc đầu tiên của bạn, sử dụng tài sản riêng.

0

Nếu bạn đang sử dụng C++ 11, hãy sử dụng delete. Lý do là nó làm cho cuộc gọi rõ ràng và rõ ràng. Bạn vẫn có thể vô tình sử dụng một hàm tạo riêng (ví dụ: trong một phạm vi giới hạn phạm vi), nhưng trình biên dịch sẽ cấm bạn sử dụng một hàm tạo bị xóa.

Một vấn đề của nhà xây dựng tư nhân là lớp và bạn bè vẫn có thể sử dụng nó - kết quả này không có lỗi truy cập nhưng lỗi liên kết, có thể khó theo dõi lại cuộc gọi.

Nếu dãy công cụ cần thiết của bạn không hỗ trợ nhà xây dựng đã xóa (= delete), bạn không nên xác định nó (như đã thấy trong câu hỏi của bạn) - chỉ tuyên bố nó và để nó không xác định, ví dụ như: private: \n Track(const Track&);

0

Trong trường hợp đầu tiên, về cơ bản bạn đang khai báo một hàm tạo bản sao riêng và sau đó không cung cấp bất kỳ triển khai nào. Bằng cách tuyên bố chúng riêng tư, không phải thành viên không thể sao chép nó.

Trong trường hợp thứ hai, cú pháp cấm bản sao được tạo. Đây là bản gốc C++.

Sự khác biệt chính khi lập trình viên có thể đọc và hiểu mã. Trường hợp đầu tiên là dư thừa, tại sao khai báo hàm tạo bản sao, làm cho nó trở thành riêng tư và không thực hiện nó. Khách hàng phải phỏng đoán rất nhiều ở đây.

Bạn chỉ có thể sử dụng "= xóa" và ngụ ý rõ ràng những gì bạn đang cố gắng làm.

Các vấn đề liên quan