2013-07-07 51 views
11

Có phải chức năng bạn bè phải được xác định rõ ràng bên ngoài lớp học không?
Nếu vậy tại sao tôi có thể khai báo một hàm bạn bè bên trong một định nghĩa lớp giống như bất kỳ hàm thành viên nào?
Đây là gì?
Chỉ với một số nhà khai thác chẳng hạn như nhà điều hành < hoặc có thể áp dụng cho tất cả các nhà khai thác không?
Nếu có thể áp dụng cho tất cả, Có bất kỳ bất lợi nào khi thực hiện việc này không?
Có nên tránh không? Nếu vậy tại sao?Tại sao có thể đặt định nghĩa chức năng người bạn bên trong định nghĩa lớp?

class person 
{ 
public: 
    bool operator<(int num) 
    { 
     return x < num ? true : false ; 
    } 
    bool operator<(person& p) 
    { 
     return x < p.x ? true : false ; 
    } 

    friend bool operator<(int num, person &p) 
    { 
     return p.x < num ? true : false ; 
    } 

    void setX(int num) 
    { 
     x = num; 
    } 

private: 
    int x; 


}; 

Cập nhật:
Tôi không yêu cầu cho việc lựa chọn phi thành viên điều hành quá tải hoặc người điều khiển thành viên quá tải.
Điều tôi muốn biết là:
Tại sao chúng tôi được phép di chuyển định nghĩa phương pháp bạn bè trong định nghĩa lớp của chúng tôi theo định nghĩa ?.
Nó không vi phạm bất kỳ điều gì? Nếu nó không phải là, Tại sao chúng ta sẽ có bạn bè ở vị trí đầu tiên?
Chúng tôi chỉ đơn giản là xác định tình trạng quá tải của các hàm thành viên. Nhưng tôi đang nói về điều này, Tại sao trình biên dịch không phàn nàn rằng tôi không định nghĩa hàm bạn bè bên ngoài định nghĩa lớp vì nó không có t cần phải được bên trong của nó (vì tham số lớp nó có) Vậy tại sao chúng ta được phép định nghĩa một hàm bạn bè bên trong một định nghĩa lớp?

+0

Nếu bạn hỏi về định nghĩa của hàm 'friend', thì bạn nên thay đổi tiêu đề câu hỏi để phản ánh điều đó. – juanchopanza

+0

tôi nên viết gì? – Breeze

+0

Bạn có thể làm điều đó vì tiêu chuẩn cho phép nó một cách rõ ràng. Đối với lý do tại sao tiêu chuẩn cho phép nó - tôi đoán là nó được coi là đủ thuận tiện để có giá trị nó. –

Trả lời

3

Vì một toán tử cần biết chi tiết về phía bên phải của biểu thức được sử dụng, nếu nó phải truy nhập dữ liệu cá nhân thuộc loại nằm ở bên đó, cần phải là friend với lớp đó.

Nếu bạn đang cố gắng để so sánh một int với một Person, như trong ví dụ của bạn, lựa chọn hai:

  • hoặc bạn cung cấp một chuyển đổi ngầm từ Person để int để < có thể sử dụng nó mà không cần truy cập vào bất kỳ lĩnh vực tư nhân
  • hoặc bạn khai báo các nhà điều hành như friend của Person để nó có thể truy cập vào x trong RHS của sự so sánh
+3

Điều đó vẫn có thể xảy ra nếu chỉ khai báo bạn bè nằm trong định nghĩa lớp, với định nghĩa hàm bạn bè được giữ bên ngoài nó. –

+0

Cảm ơn, Nhưng tôi đã không lý do tại sao chúng tôi sử dụng bạn bè, tôi hỏi lý do tại sao chúng tôi được phép di chuyển định nghĩa của phương pháp bạn bè bên trong định nghĩa lớp học của chúng tôi. Nó không vi phạm bất kỳ điều gì? Nếu không, Tại sao chúng ta sẽ có những người bạn ở vị trí đầu tiên, Chúng ta có thể định nghĩa các overload là các hàm thành viên (tôi biết các hạn chế của các hàm thành viên). chức năng người bạn bên ngoài một định nghĩa lớp vì nó không cần phải ở bên trong nó (vì tham số lớp mà nó có) – Breeze

+0

Tôi đề nghị bạn hãy xem ở đây: http://stackoverflow.com/questions/4421706/operator-overloading/ 4421729 # 4421729 – Jack

0

như Jack mentio chức năng người bạn ned được yêu cầu ở những nơi truy cập vào dữ liệu cá nhân là cần thiết. Ngoài ra còn có một mục đích khác. Điều này liên quan đến các loại thừa kế. Chỉ có lớp dẫn xuất và bạn bè của nó có thể chuyển đổi con trỏ thành một cơ sở riêng thành một kiểu dẫn xuất. Vì vậy, đôi khi bạn có thể muốn làm cho một số chức năng một người bạn của lớp có nguồn gốc để cho phép bên trong cơ thể chức năng này.

8

Có phải chức năng bạn bè phải được xác định rõ ràng bên ngoài lớp học không?

Chức năng của bạn có thể được xác định trong khai báo lớp. Các hàm này là các hàm inline, và giống như các hàm nội tuyến của thành viên mà chúng hoạt động như thể chúng đã được định nghĩa ngay sau khi tất cả các thành viên lớp đã được nhìn thấy nhưng trước khi phạm vi lớp được đóng (kết thúc khai báo lớp). Các chức năng của người bạn được định nghĩa trong các khai báo lớp không được xem xét trong phạm vi của lớp kèm theo; chúng nằm trong phạm vi tệp. quote

Là nó chỉ OK với một số nhà khai thác như < điều hành hoặc là nó được áp dụng cho tất cả các nhà khai thác?

Tốt nhất là cố gắng tránh các chức năng của bạn vì chúng đối diện với những gì bạn đang cố gắng thực hiện bằng cách sử dụng phạm vi lớp riêng và chủ yếu là "ẩn" các biến. Nếu tất cả các hàm của bạn là các hàm của bạn thì sử dụng các biến riêng là gì?

Tuy nhiên, có một số nhà khai thác chung mà thường được khai báo là chức năng bạn bè, những người đang có operator<<operator>>

+0

Cảm ơn bạn rất nhiều :) Tôi không cố gắng khai báo tất cả các chức năng cần thiết của tôi như bạn bè, tôi là curios để biết lý do tại sao một chức năng bạn bè (được sử dụng duy nhất đối với hoạt động quá tải và không có gì khác) có thể được định nghĩa bên trong một lớp và tại sao nó được cho phép – Breeze

+0

@Hossein báo tôi đã cho bạn không nói một cách bình thường "tại sao nó được phép" nhưng giải thích tại sao "nó không được phép". –

+0

tôi biết, nhưng phần "Bạn bè có thể được xác định bên trong khai báo lớp", nói rằng chúng tôi được thừa nhận làm như vậy, tôi hiểu rằng chức năng của bạn không phải là câu trả lời cho mọi thứ như bạn đã đề cập rõ ràng, khi tôi nói vậy, tôi có nghĩa là phần trích dẫn mà kinda xóa các phần của câu hỏi của tôi – Breeze

0

Alexandru Barbarosie câu trả lời là đúng. Nó có nghĩa là chúng ta có thể khai báo một hàm friend, mà không phải là một hàm thành viên, trong một lớp. Điều này có thể được tốt đẹp để tổ chức các mã. Tôi nghĩ rằng một ví dụ có thể giúp để hiểu nó trong trường hợp nó không rõ ràng.

#include <iostream> 

class A { 
    public: 
     A(int val) : val(val) {} 
     // The following isn't a member function, it is a friend 
     // function declared inside the class and it has file scope 
     friend void draw (A &a) { 
      std::cout << "val: " << a.val << "\n"; 
     } 
    private: 
     int val; 
}; 

int main() { 
    A a(5); 
    draw(a); // outputs "val: 5" 
    //A::draw(a); // Error: 'draw' is not a member of 'A' 
} 
Các vấn đề liên quan