друг в операторе == или << когда мне его использовать? - PullRequest
13 голосов
/ 03 октября 2010

Я чувствую, что у меня немного дыра в понимании ключевого слова friend.

У меня есть класс, presentation.Я использую его в своем коде для двух переменных, present1 и present2, которые сравниваем с ==:

if(present1==present2)

Вот как я определил оператор ==class presentation):

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

Однако мне сказали, что лучше использовать friend и определять его вне класса:

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

Почему?Какая разница между ними?

Ответы [ 5 ]

13 голосов
/ 03 октября 2010

Ваше решение работает, но оно менее мощное, чем подход friend.

Когда класс объявляет функцию или другой класс как friend, это означает, что функция или класс друга имеет доступ к объявленному классу.рядовые и защищенные члены.Это как если бы объявленная сущность была членом декларирующего класса.

Если вы определяете operator==() как функцию-член, то, как и в случае friend, функция-член имеет полный доступ к членам класса.,Но поскольку это функция-член, она определяет единственный параметр, поскольку первый параметр подразумевается как this: объект типа presentation (или его потомок).Однако, если вы определяете функцию как не являющуюся членом, вы можете указать оба параметра, и это даст вам возможность сравнивать любые два типа, которые могут быть преобразованы в presentation, используя ту же функцию.

Например:

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 );
}

Наконец, возникает вопрос «почему декларация friend?».Если функция operator==() не нуждается в доступе к закрытым членам presentation, тогда действительно лучшее решение - сделать ее функцией, не являющейся членом, не являющейся другом.Другими словами, не предоставляйте функции права доступа, которые не нужны.

2 голосов
/ 03 октября 2010

В первом случае ваша функция operator== является нестатическим членом класса.Следовательно, он имеет доступ к закрытым и защищенным переменным-членам.

Во втором случае оператор объявляется извне, поэтому он должен быть определен как друг класса для доступа к этим переменным-членам.

1 голос
/ 03 октября 2010

Мне нравится ответ Бенуа (но я не могу его проголосовать), но я полагаю, что пример не помешает уточнить его. Вот некоторый код денег, который у меня есть (предположим, все остальное помещено правильно):

// 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;
}

Надеюсь, это поможет.

0 голосов
/ 03 октября 2010

Оператор, реализованный как метод, может быть вызван только в том случае, если левое выражение является переменной (или ссылкой на объект) класса, для которого определен оператор.

В случае operator== обычно вас интересует сравнение двух объектов одного класса. Реализация, как метод решает вашу проблему здесь.

Однако представьте, что вы пишете строковый класс и хотите, чтобы оператор работал в этом сценарии:

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

Чтобы сделать выражение s1 == s2 допустимым, вы должны определить opetator== как функцию, внешнюю по отношению к MyString классу.

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

Если оператору нужен доступ к закрытым членам вашего класса, он должен быть другом вашего класса.

В случае операторов << и >>, работающих с потоками, вы определяете оператор, левый операнд которого является экземпляром потока, а правый - вашим классом, поэтому они не могут быть методами вашего класса. , Как и в приведенном выше примере, они должны быть функциями, внешними для вашего класса и друзей, если требуется доступ к закрытым членам.

0 голосов
/ 03 октября 2010

Взгляните на этот дубликат Сорта здесь: функция "должен оператор быть реализован как друг или как член"

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

В вашем случае имеет смысл реализовать его как часть класса.Метод Friend используется (и полезен) для случаев, когда используется более одного типа, и часто не применяется к == и !=.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...