2010-10-03 33 views
9

Tôi cảm thấy mình có chút hiểu biết về từ khóa friend.người bạn trong toán tử == hoặc << khi nào tôi nên sử dụng?

Tôi có một lớp học, presentation. Tôi sử dụng nó trong mã của tôi cho hai biến, present1present2, mà tôi so sánh với ==:

if(present1==present2) 

Đây là cách tôi định nghĩa toán tử == (trong class presentation):

bool operator==(const presentation& p) const; 

Tuy nhiên, tôi đã nói rằng sử dụng friend và xác định nó bên ngoài lớp học là tốt hơn:

friend bool operator==(presentation&, presentation&); 

Tại sao ? Sự khác nhau giữa hai cái là gì?

+0

-1 không đầy đủ và bot dễ hiểu –

+2

Đối với tôi, điều đó hoàn toàn dễ hiểu. Toán tử == có nên là một hàm bạn bè bên ngoài một lớp hay được định nghĩa bên trong lớp không? – Benoit

+0

Một bot có thể hiểu câu hỏi này? > _> – Rao

Trả lời

2

Trong trường hợp đầu tiên, chức năng của bạn operator== là thành viên không phải là lớp học. Do đó, nó có quyền truy cập vào các biến thành viên riêng tư và được bảo vệ.

Trong trường hợp thứ hai, toán tử được khai báo bên ngoài, do đó nó phải được định nghĩa là bạn của lớp để truy cập vào các biến thành viên đó.

+1

Ok, nhưng tại sao tôi muốn nó được khai báo bên ngoài? hiện nó vẫn bên ngoài mặc dù tuyên bố được liệt kê bên trong lớp là công khai? và là người đầu tiên ok? – Nadav

+0

Cả hai công việc. Nhưng trong trường hợp thứ hai, hàm không phải là một phần của lớp, ngay cả khi nó có thể nằm trong cùng một tệp tiêu đề. – Benoit

1

Tôi thích câu trả lời của Benoit (nhưng tôi không thể bỏ phiếu), nhưng tôi thấy một ví dụ sẽ không làm tổn thương để làm rõ nó. Dưới đây là một số Mã tiền tôi có (giả sử mọi thứ khác được đặt đúng):

// header file 
friend bool operator ==(const Money, const Money); // are the two equal? 

// source file 
bool operator ==(const Money a1, const Money a2) 
{ 
    return a1.all_cents == a2.all_cents; 
} 

Hy vọng điều đó sẽ hữu ích.

11

Giải pháp của bạn hoạt động, nhưng nó ít mạnh hơn cách tiếp cận friend.

Khi lớp tuyên bố một hàm hoặc một lớp khác là friend điều đó có nghĩa là hàm hoặc lớp bạn bè có quyền truy cập vào các thành viên được bảo mật và bảo mật của lớp tuyên bố. Nó như thể thực thể được khai báo là một thành viên của lớp khai báo.

Nếu bạn xác định operator==() làm hàm thành viên thì giống như trường hợp friend, chức năng thành viên có toàn quyền truy cập vào các thành viên của lớp học. Nhưng vì nó là một hàm thành viên, nó chỉ định một tham số duy nhất, vì tham số đầu tiên được ngụ ý là this: một đối tượng kiểu presentation (hoặc một hậu duệ của nó). Tuy nhiên, nếu bạn xác định hàm là không phải thành viên thì bạn có thể chỉ định cả hai tham số và điều này sẽ cho bạn sự linh hoạt khi so sánh hai loại có thể đúc thành một presentation sử dụng cùng chức năng đó.

Ví dụ:

class presentation { 
    friend bool operator==(const presentation&, const presentation&); 
    // ... 
}; 

class Foo : public presentation { /* ... */ }; 
class Bar : public presentation { /* ... */ }; 

bool operator==(const presentation& p1, const presentation& p2) 
{ 
    // ... 
} 

bool func(const Foo& f, const Bar& b, const presentation& p) 
{ 
    return f == b || f == p); 
} 

Cuối cùng, điều này đặt ra câu hỏi "tại sao tờ khai friend?". Nếu chức năng operator==() không cần quyền truy cập vào các thành viên riêng tư của presentation thì thực sự giải pháp tốt nhất là làm cho nó trở thành một chức năng không phải là thành viên, không phải bạn bè. Nói cách khác, không cung cấp cho một đặc quyền truy cập chức năng mà không cần.

+0

Tôi nghĩ nó có hiệu quả trong vấn đề phong cách. Nếu luôn luôn làm cho người vận hành quá tải các hàm bên ngoài (ngay cả khi nó không cần thiết), thì tất cả các quá tải của toán tử sẽ là "cùng nhau" bên ngoài lớp. –

+0

thnx rất nhiều +1. tôi đoán tôi không thể đánh dấu 2 câu trả lời. – Nadav

+0

@Emile: Tôi nghĩ nó có thể hoạt động như wilhelmtell nói. Nếu bạn thực hiện thành viên 'operator ==' (và các toán tử khác), thì khi bạn sử dụng nó, bạn sẽ có được sự chuyển đổi ngầm định trên rh, nhưng không phải là lhs. Nếu bạn thực hiện nó như là một hàm không phải thành viên, bạn sẽ nhận được chuyển đổi ngầm trên cả hai. Phong cách là tất cả rất tốt, nhưng có một số nhà khai thác không thể được quá tải bằng cách sử dụng chức năng không phải thành viên, vì vậy nó chỉ đưa bạn cho đến nay. –

0

Hãy xem này sorta lặp lại ở đây: should-operator-be-implemented-as-a-friend-or-as-a-member-function

là gì quan trọng chỉ ra, câu hỏi liên quan này là về <<>> mà phải được thực hiện như bạn bè kể từ khi hai toán hạng là các loại khác nhau.

Trong trường hợp của bạn, bạn nên triển khai nó như là một phần của lớp học. Kỹ thuật bạn bè được sử dụng (và hữu ích) đối với trường hợp có nhiều loại được sử dụng và thường không áp dụng cho ==!=.

0

Một toán tử được thực hiện như một phương thức, chỉ có thể được gọi, nếu biểu thức bên tay trái là một biến (hoặc tham chiếu đến đối tượng) của lớp, toán tử được định nghĩa.

Trong trường hợp operator== thường bạn quan tâm đến việc so sánh hai đối tượng của cùng một lớp. Thực hiện, như một phương pháp giải quyết vấn đề của bạn ở đây.

Hãy tưởng tượng tuy nhiên, bạn viết một lớp string và bạn muốn một nhà điều hành, làm việc trong kịch bản này:

const char *s1 = ... 
MyString s2 = ... 
if(s1 == s2){... 

Để thực hiện các biểu hiện s1 == s2 quy phạm pháp luật, bạn phải xác định một opetator== như một chức năng bên ngoài để MyString lớp học.

bool operator==(const char *, const MyString&); 

Nếu nhà điều hành cần quyền truy cập vào các thành viên riêng nếu lớp học của bạn, bạn phải là bạn của lớp học.

Trong trường hợp người vận hành <<>>, hoạt động trên luồng, bạn xác định toán tử, toán hạng bên trái là trường hợp luồng và trường hợp bên phải là lớp của bạn, vì vậy chúng không thể là phương thức của lớp học. Giống như trong ví dụ trên, chúng phải là các hàm bên ngoài lớp và bạn bè của bạn, nếu cần truy cập vào các thành viên riêng.

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