Я читал, что перегруженный оператор, объявленный как функция-член, является асимметричным, потому что он может иметь только один параметр, а другой параметр, передаваемый автоматически, является this
указателем. Так что не существует стандарта для их сравнения. С другой стороны, перегруженный оператор, объявленный как a, friend
является симметричным, потому что мы передаем два аргумента одного и того же типа и, следовательно, их можно сравнивать.
У меня вопрос: когда я все еще могу сравнивать lvalue указателя со ссылкой, почему предпочтение отдается друзьям? (использование асимметричной версии дает те же результаты, что и симметричная) Почему алгоритмы STL используют только симметричные версии?
Ответы:
Если вы определяете свою перегруженную оператором функцию как функцию-член, компилятор переводит такие выражения, как
s1 + s2
вs1.operator+(s2)
. Это означает, что перегруженная оператором функция-член вызывается для первого операнда. Так работают функции-члены!Но что, если первый операнд не является классом? Большая проблема возникает, если мы хотим перегрузить оператор, первый операнд которого, скорее, не является типом класса
double
. Итак, вы не можете так писать10.0 + s2
. Однако вы можете написать перегруженную оператором функцию-член для таких выражений, какs1 + 10.0
.Чтобы решить эту проблему с упорядочением , мы определяем перегруженную функцию оператора как
friend
ЕСЛИ ей нужен доступ кprivate
членам. Делайте этоfriend
ТОЛЬКО, когда ему нужен доступ к закрытым членам. В противном случае просто сделайте это функцией, не являющейся другом, чтобы улучшить инкапсуляцию!Прочтите это:
Небольшая проблема с упорядочением в операндах
Как функции, не являющиеся членами, улучшают инкапсуляцию
источник
friend
только тогда, когда ему нужен доступ к закрытым членам ... и когда у вас нет / вам надоело писать аксессоры, не так ли?a/b
.friend
- реализовать их в терминах операторов присваивания операции (которые почти наверняка будут открытыми членами). Например, вы можете определитьT T::operator+=(const T &rhs)
как член, а затем определить не членT operator(T lhs, const T &rhs)
какreturn lhs += rhs;
. Функция, не являющаяся членом, должна быть определена в том же пространстве имен, что и класс.Это не обязательно различие между
friend
перегрузками операторов и перегрузками операторов функций-членов, как между перегрузками глобальных операторов и перегрузками операторов функций-членов.Одна из причин, по которой следует предпочесть перегрузку глобального оператора, заключается в том, что вы хотите разрешить выражения, в которых тип класса отображается справа от двоичного оператора. Например:
Это работает, только если есть глобальная перегрузка оператора для
Обратите внимание, что перегрузка глобального оператора не обязательно должна быть
friend
функцией. Это необходимо только в том случае, если ему нужен доступ к закрытым членамFoo
, но это не всегда так.В любом случае, если бы была
Foo
только перегрузка оператора функции-члена, например:... тогда мы сможем иметь только выражения, в которых
Foo
экземпляр появляется слева от оператора плюса.источник