Вы должны быть очень осторожны с тем, когда / где вы используете ключевое слово friend
, и, как и вы, я использовал его очень редко. Ниже приведены некоторые примечания по использованию friend
и альтернативам.
Допустим, вы хотите сравнить два объекта, чтобы увидеть, равны ли они. Вы можете либо:
- Используйте методы доступа для сравнения (проверьте каждый ivar и определите равенство).
- Или вы можете получить доступ ко всем участникам напрямую, сделав их публичными.
Проблема с первой опцией заключается в том, что это может быть МНОГО аксессоров, которые (немного) медленнее, чем прямой доступ к переменным, труднее для чтения и громоздки. Проблема второго подхода заключается в том, что вы полностью нарушаете инкапсуляцию.
Что было бы хорошо, если бы мы могли определить внешнюю функцию, которая могла бы по-прежнему получать доступ к закрытым членам класса. Мы можем сделать это с помощью ключевого слова friend
:
class Beer {
public:
friend bool equal(Beer a, Beer b);
private:
// ...
};
Метод equal(Beer, Beer)
теперь имеет прямой доступ к a
и b
закрытым членам (которые могут быть char *brand
, float percentAlcohol
и т. Д.) Это довольно надуманный пример, который вы скорее примените friend
до перегруженного == operator
, но мы вернемся к этому.
Несколько замечаний:
- A
friend
НЕ является функцией-членом класса
- Это обычная функция со специальным доступом к закрытым членам класса
- Не заменяйте все аксессоры и мутаторы друзьями (вы также можете сделать все
public
!)
- дружба не взаимна
- дружба не транзитивна
- Дружба не наследуется
- Или, как объясняется в C ++ FAQ : «То, что я предоставляю вам дружеский доступ ко мне, автоматически не дает вашим детям доступ ко мне, автоматически не дает вашим друзьям доступ ко мне, и автоматически не дает мне доступ к вам. "
Я действительно использую friends
только тогда, когда это намного сложнее сделать другим способом. В качестве другого примера, многие векторные математические функции часто создаются как friends
из-за взаимодействия Mat2x2
, Mat3x3
, Mat4x4
, Vec2
, Vec3
, Vec4
и т. Д. И это просто так Гораздо проще быть друзьями, чем везде пользоваться аксессуарами. Как уже отмечалось, friend
часто полезен применительно к <<
(очень удобно для отладки), >>
и, возможно, к оператору ==
, но также может использоваться для чего-то вроде этого:
class Birds {
public:
friend Birds operator +(Birds, Birds);
private:
int numberInFlock;
};
Birds operator +(Birds b1, Birds b2) {
Birds temp;
temp.numberInFlock = b1.numberInFlock + b2.numberInFlock;
return temp;
}
Как я уже сказал, я не очень часто использую friend
, но время от времени это именно то, что вам нужно. Надеюсь, это поможет!