2011-12-26 14 views
5

Giả sử tôi có một lớp không hỗ trợ sao chép thành viên, vì vậy tôi không muốn bảo toàn trình tạo bản sao và nhà điều hành gán trình biên dịch. Tôi cũng không muốn thực hiện những vì một trong haiLiệu "toán tử =" trả về loại vấn đề nếu tôi muốn làm cho lớp không thể sao chép được?

  1. làm như vậy phải cố gắng hơn và tôi không cần những người hoạt động trong lớp học của tôi hoặc
  2. những hoạt động sẽ không có ý nghĩa trong lớp học của tôi

vì vậy tôi muốn cấm chúng. Để làm như vậy I'll declare them private and provide no implementation:

class NonCopyable { 
private: 
    NonCopyable(const NonCopyable&); //not implemented anywhere 
    void operator=(const NonCopyable&); //not implemented anywhere 
}; 

Bây giờ tôi có thể chọn bất kỳ kiểu trả về cho operator=() hàm thành viên. Tôi có chọn loại trả lại nào không?

+2

Cũng lưu ý rằng với C++ 11 bạn có thể làm điều này rõ ràng hơn bằng cách thực hiện 'void operator = (const NonCopyable &) = delete;' –

Trả lời

1

Điều quan trọng một nhỏ, chút xíu:

  • void đảm bảo một tỷ lệ nhỏ của các cuộc gọi ngẫu nhiên/sai lầm (a = b = c/f (d = e)) từ bên trong việc thực hiện của lớp sản xuất biên dịch lỗi thời gian hơn là lỗi thời gian liên kết, có thể tiết kiệm thời gian biên dịch và dễ hiểu hơn (tối thiểu có liên quan cho các lớp lớn được nhiều nhà phát triển cảm động, một số có giới hạn trước đây quen thuộc).

  • void sẽ rung một hồi chuông báo động đối với tôi (và hy vọng nhất các nhà phát triển), tự hỏi liệu bạn:

    • muốn loại bỏ các mặc định tạo operator=
    • chỉ là lười biếng về gõ thêm, hoặc
    • không quen thuộc/không rõ ràng về ngữ nghĩa chung được mong đợi là operator=.

Với câu hỏi mở trong tâm trí, lập trình viên khác ít có khả năng đi cùng và nghĩ rằng bạn chỉ đã không nhận được xung quanh để cung cấp việc thực hiện và thêm nó tình cờ (bạn có thể cảm thấy bình luận đầy đủ).

  • trả về một tham chiếu đến nhập có thể làm cho chữ ký chức năng tổng thể ngay lập tức hơn dễ nhận biết, hoặc tìm kiếm trực quan qua một loại phức tạp để tìm operator= có thể có tác dụng ngược lại - tất cả trong mắt (và tâm trí) của khán giả ....
+0

+1, không suy nghĩ về các lỗi biên dịch thời gian so với thời gian liên kết –

2

Không, vì bạn sẽ không bao giờ gọi nhà điều hành này trong mã của mình. Tôi có xu hướng giữ kiểu trả về NonCopyable &, để rõ ràng và nhất quán.

7

Không, loại trả lại không quan trọng.

C++ chuẩn không áp đặt bất cứ yêu cầu về kiểu trả về cho phân copy hàm thành viên đặc biệt bạn khai báo chính mình. Nó chỉ cần là một operator=() có nghĩa là "chính xác một thông số của loại X, X&, const X&, volatile X& hoặc const volatile X&". †† Do đó, void operator=(const NonCopyable&); vẫn là một toán tử gán bản sao (một toán tử do người dùng khai báo, cụ thể).

Vì thực tế bạn đã cung cấp toán tử gán bản sao của riêng mình, nó sẽ làm thay thế thế hệ của toán tử gán bản sao mặc định. Điều này buộc tất cả các cuộc gọi đến nhà điều hành gán bản sao của NonCopyable để giải quyết cho bạn, gây ra bất kỳ nỗ lực nào để sử dụng toán tử gán bản sao để không biên dịch vì nó được khai báo private.

class Foo : NonCopyable 
{ 
}; 

int main() 
{ 
    Foo a; 
    Foo b; 
    // Compiler complains about `operator=(const NonCopyable&)` 
    // not accessible or something like that. 
    a = b; 
} 

Và vì tôi sẽ không bao giờ có thể thực sự sử dụng nó, điều quan trọng không phải là toán tử gán bản sao chuẩn. Nếu tôi cố gắng sử dụng toán tử gán bản sao nó sẽ dẫn đến lỗi trình biên dịch, đó chính là điều bạn muốn.


† Tất nhiên, điều quan trọng là, nếu nhà điều hành gán bản sao thực sự làm điều gì đó. Nói chung, bạn muốn các nhà khai thác của bạn cư xử giống như những người được xây dựng trong, do đó, trở về một X& là thực hành tốt khi bạn đang thực sự làm nhiệm vụ.

†† C++ Tiêu chuẩn: đối tượng 12,8 lớp sao chép [class.copy]

Một người dùng tuyên bố bản sao phân công điều hành X::operator= là một tổ chức phi tĩnh phi mẫu hàm thành viên của lớp X với chính xác một thông số loại X, X&, const X&, volatile X& hoặc const volatile X&.

1

Không, bởi vì bạn có thể trả lại bất kỳ thứ gì từ operator=, ngay cả khi bạn xác định việc triển khai.

1

Không, điều đó không quan trọng vì bạn không bao giờ thực hiện tuyên bố return. Nếu bạn cố gắng gọi toán tử, trình biên dịch sẽ không thể tìm thấy triển khai (với bất kỳ loại nàoreturn, do đó loại trả lại không liên quan).

Điều thú vị là, toán tử gán bản sao của boost::noncopyable được khai báo trả lại số const noncopyable&, nhưng tôi đoán đó chỉ là quy ước.

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