2013-07-07 8 views
11

Не предполагается ли явное определение функции друга вне класса?
Если да, то почему я могу объявить функцию друга внутри определения класса так же, как любую функцию-член?
Что это?
Это нормально с некоторыми операторами, такими как оператор < или применим ли он ко всем операторам?
Если это применимо ко всем из них, есть ли недостатки для этого?
Следует ли его избегать? Если да, то почему?Почему возможно определить определения функций друга внутри определения класса?

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; 


}; 

Update:
Я не прошу для выбора оператора, не являющийся член перегружать или оператор члена перегружать.
Что я хочу знать, так это то, что:
Почему нам разрешено перемещать определение методов друзей в нашем определении класса? ?.
Разве это не нарушение каких-либо вещей? Если это не так, почему у нас есть друзья на первом месте?
Мы могли бы просто определить перегрузки как функции-члены (я знаю ограничения функций-членов) Но я говорю, зная это, Почему не компилятор жалуется, что я не определил функцию друга вне определения класса, t должно быть внутри него (из-за его параметра класса) Итак, почему нам разрешено определять функцию друга внутри определения класса?

+0

Если вы спрашиваете об определении функции 'friend', вы должны изменить заголовок своего вопроса, чтобы это отразить. – juanchopanza

+0

Что мне тогда писать? – Breeze

+0

Вы можете сделать это, потому что стандарт явно разрешает это. Что касается причины, по которой стандарт позволяет это, я предполагаю, что она считалась достаточно удобной, чтобы ее стоило. –

ответ

3

Поскольку оператор, которому необходимо знать детали правой части выражения, в котором используется, если он должен получить доступ к личным данным того типа, который находится на этой стороне, он должен быть friend с этим классом.

Если вы пытаетесь сравнить Int с Person, как в вашем примере, выбор два:

  • или обеспечить неявное преобразование из Person в INT, так что < может использовать его без доступа к любой частное поле
  • или объявление оператора, как friend из Person так, что он может получить доступ к й в правой части сравнения
+3

Это было бы возможно, если внутри определения класса находилось только объявление друга, а определение функции друга хранилось вне его. –

+0

Спасибо, Но я не сделал почему мы используем друзей, я спросил, почему нам разрешено переместить определение методов друзей внутри нашего определения класса. Разве это не нарушает никаких вещей? Если это не так, почему у нас есть друзья на первом месте, мы могли бы просто определить перегрузки как функции-члены (я знаю ограничения функций-членов), но я говорю, зная это, почему компилятор не жалуется, что я не определил друга за пределами определения класса, так как он не должен быть внутри него (из-за его параметра класса) – Breeze

+0

Предлагаю вам посмотреть здесь: http://stackoverflow.com/questions/4421706/operator-overloading/ 4421729 # 4421729 – Jack

0

Как Джек mentio в местах, где необходим доступ к конфиденциальным данным. Есть и другая цель. Это связано с типами наследования. Только производный класс и его друзья могут преобразовать указатель на частную базу в производный тип. Поэтому иногда вы можете сделать некоторую функцию другом производного класса, чтобы позволить этому внутреннему телу функции.

8

Не предполагается ли явное определение функции друга вне класса?

Функции друга могут быть определены внутри деклараций классов. Эти функции являются встроенными функциями и похожими на встроенные функции членов, они ведут себя так, как если бы они были определены сразу после того, как все члены класса были замечены, но до того, как область класса закрыта (конец объявления класса). Функции друга, определенные внутри деклараций классов, не рассматриваются в области охватывающего класса; они находятся в области файлов. quote

Является ли это только в порядке с некоторыми операторами таких как < оператора или это применимо ко всем операторам?

Лучше всего стараться избегать функций друга, поскольку они противоположны тому, что вы пытаетесь сделать, используя частный класс и главным образом «спрячь» переменные. Если все ваши функции - это функции друзей, то в чем заключается использование личных вариаций?

Тем не менее, существуют некоторые общие операторы, которые часто объявляемых как друга функции, те operator<< и operator>>

+0

Спасибо большое :) Я не пытаюсь объявить все мои необходимые функции в качестве друзей, я был любопытным, чтобы узнать, почему функция друга (которая используется исключительно для оперативной перегрузки и ничего другого) можно определить внутри класса и почему это разрешено – Breeze

+0

@ Хоссейн Цитата, которую я вам дал, не говорит «почему это разрешено», но объясняет, почему «это не разрешено». –

+0

Я знаю, но часть «Функции друга могут быть определены внутри деклараций классов», говорит, что нам это предписано, я понимаю, что функции друзей не являются ответом на все, как вы также четко упомянули, когда я говорил это, я имел в виду цитируемый раздел, который как бы очистил части моего вопроса – Breeze

0

Александр Барбэрошие ответ является правильным. Это означает, что мы можем объявить функцию друга, которая не является функцией-членом, внутри класса. Это может быть удобно организовать код. Я думаю, что пример может помочь понять это, если это не ясно.

#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' 
}