Функция-оператор может быть другом класса, а не только его членом. Как было показано ранее в этой главе, поскольку функции-друзья не являются членами класса, они не могут иметь неявный аргумент this. Поэтому при использовании дружественной функции-оператора оба операнда передаются функции при перегрузке бинарных операторов, а при перегрузке унарных операторов передается один операнд. Следующие операторы не могут использовать перегрузку с помощью функций-друзей: =, (), [], и ->. Остальные операторы могут быть перегружены как с помощью функций-членов, так с помощью функций-друзей. В качестве примера ниже рассматривается модифицированная версия предыдущей программы, в которой оператор + перегружен с помощью дружественной функции:
Как можно видеть, в данном случае оба операнда передаются функции operator+(). Левый операнд передается в переменной p1, а правый — в переменной р2.
Во многих случаях использование функций-друзей вместо функций-членов не дает выигрыша при перегрузке операторов. Однако имеется одна ситуация, в которой необходимо использовать дружественные функции. Как известно, указатель на объект, вызывающий функцию-оператор, передается в указателе this. В случае бинарных операторов левый объект вызывает эту функцию. Такой способ работает до тех пор, пока левый объект определяет заданную операцию. Предположим, что для объекта A определены операции присваивания и сложения, так что следующий код
A = A + 10;
является корректным. Поскольку объект A находится с левой стороны оператора +, то он вызывает функцию-оператор, перегружающую операцию сложения, которая по предположению способна добавить целое число к определенному элементу объекта A. Однако следующая инструкция не является корректной:
A = 10 + A; // не будет работать
Причина, по которой эта инструкция не будет выполняться, заключена в том, что слева от оператора + теперь стоит целое число, являющееся встроенным типом и не имеющее функции-члена, которая могла бы осуществить сложение с объектом A.
Можно использовать встроенные типы с левой стороны оператора +, если перегрузка осуществляется с помощью двух дружественных функций. В таком случае функции-оператору явным образом передаются оба аргумента и она вызывается точно так же, как любая перегруженная функция, основываясь на типе своих аргументов. Одна из версий функции-оператора + обрабатывает суммирование объект + целое, а вторая обрабатывает суммирование целое + объект. Перегрузка оператора + (или любого другого бинарного оператора) с использованием дружественных функций позволяет складывать переменные встроенных типов с объектами в любом порядке.