2012-05-13 41 views
29

Đó là thực hành tốt nhất (trong trường hợp này):So sánh điều hành quá tải

bool Foo::operator==(const Foo& other) { 
    return bar == other.bar; 
} 

// Implementation 1 
bool Foo::operator!=(const Foo& other) { 
    return bar != other.bar 
} 

// Implementation 2 
bool Foo::operator!=(const Foo& other) { 
    return !(*this == other); 
} 

Đối với các nhà khai thác như>, <, < =,> = Tôi sẽ đi với thực hiện 2 khi có thể. Tuy nhiên, cho! = Tôi nghĩ rằng thực hiện 1 là tốt hơn vì một cuộc gọi phương thức khác không được thực hiện, điều này có đúng không?

+0

Tôi muốn viết nó theo cách tự nhiên nhất để thể hiện chính xác. Trình biên dịch có lẽ sẽ làm tốt công việc biên dịch nó theo cách bạn chọn. – Flexo

+0

Ok cảm ơn. Là một lưu ý phụ, tôi biết rằng nếu == là quá phức tạp, thì việc thực hiện 2 sẽ tốt hơn, nhưng đó là một trường hợp khác. – blaze

+0

Bạn nên thêm 'const' vào mỗi một trong các hàm. Cũng xem xét sử dụng các chức năng miễn phí chứ không phải là các hàm thành viên, vì các hàm trước đây là đối xứng đối với các loại và các chuyển đổi trong đó các hàm không phải là. Điều này quan trọng hơn nếu loại của bạn có thể được chuyển đổi hoàn toàn từ các loại khác. –

Trả lời

29

Triển khai thứ hai có ràng buộc đáng chú ý là == sẽ luôn là đối số boolean của !=. Đây có lẽ là những gì bạn muốn, và nó làm cho mã của bạn dễ dàng hơn để duy trì bởi vì bạn chỉ phải thay đổi một thực hiện để giữ cho hai đồng bộ.

+7

Và mọi trình biên dịch C++ trên hành tinh sẽ nội tuyến! = Cuộc gọi đến ==. – jthill

+1

@jthill Hãy cẩn thận: Sẽ không nếu nhà điều hành chưa được xác định (ví dụ: tệp nguồn). – Tim

+3

@Tim, nó có thể nếu trình biên dịch của bạn có LTO. – zneak

11

Bạn nên luôn sử dụng những gì bạn có khi quá tải toán tử so sánh. Chỉ có hai bạn cần xác định là operator==operator<. Phần còn lại bạn có thể viết về hai điều này. Nó ít bị lỗi, như thể bạn có một sai lầm, nó chỉ ở một nơi.

Một trong những tính năng chính của OOP là khả năng sử dụng lại mã. Nếu bạn đã viết mã, tại sao lại viết lại? Dính vào những gì bạn có, và bạn sẽ chỉ có một thứ để kiểm tra.

Nó giống như tuyên bố một hằng số, và sau đó sử dụng nó trong một số điểm trong suốt tệp của bạn.

+0

Thực ra, bạn chỉ cần toán tử '' <''. Bởi vì x == y là tương đương về mặt logic với! (X mdenton8

+0

@ mdenton8, Chắc chắn, nhưng nó thành ngữ để định nghĩa cả toán tử '' và 'operator ==' từ đầu nếu bạn muốn tất cả toán tử so sánh. Một số thuật toán và thùng chứa C++ STL sẽ sử dụng 'operator ==' để bình đẳng và một số sẽ sử dụng toán tử '' theo cách bạn mô tả. Đúng là nếu họ làm những việc khác nhau, bạn có thể có một số kết quả đáng ngạc nhiên khi sử dụng các thuật toán nhất định. – chris

+0

Đúng, nó thường có thể hiệu quả hơn và rõ ràng hơn. Nhưng ít bảo trì hơn cho những lý do tương tự như bạn đã đề cập ở trên. – mdenton8

4

Triển khai 2 tốt hơn vì nó sử dụng toán tử đã xác định ==. Ngoài ra những chức năng điều hành nên được const bởi vì họ không sửa đổi các đối tượng.

+0

Cảm ơn vì mẹo const – blaze

+0

Tôi không thể chắc chắn chính xác về thiết lập của mình đã gây ra điều này (boost.optional, có thể) nhưng tôi có một số lỗi lỗi như 'stl_algobase.h: 808: 22: error: no match for ' operator == ''cho đến khi tôi khai báo các hàm' const' Cảm ơn bạn đã chỉ ra điều này. – MatrixManAtYrService

1

Nói chung, triển khai 2 tốt hơn vì nhiều lý do. Trước hết, bạn không viết (gần như) mã trùng lặp. Nếu bạn cần thay đổi nó (vì lớp đã phát triển hoặc đã có lỗi), một lần nữa với việc thực hiện 2 bạn chỉ thay đổi 1 vị trí. Đó là, triển khai 2 làm cho mã của bạn nhất quán hơn và ít bị lỗi hơn.

3

Không có mục nào ở trên.

Tôi ước mình có thể tìm thấy tờ giấy thực sự chi tiết hơn về điều này nhưng tôi không thể nhớ lại tên.

Hoạt động so sánh của bạn phải ở bên ngoài. Giao diện của bạn phải đủ để tìm trạng thái của một đối tượng và trạng thái của đối tượng cần được so sánh chính tả. Bạn có thể viết "bằng" bên ngoài lớp học của bạn, và do đó bất kỳ so sánh nào thực sự, và điều đó có thể ... bạn muốn.

+2

Điều này không phải lúc nào cũng đúng. Có thể có thiết kế mà bạn không muốn cấp quyền truy cập cho tất cả trạng thái. Sau đó, một lần nữa, bạn luôn có thể cấp quyền truy cập vào một chức năng miễn phí thông qua tình bạn. –

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