С помощью функций-"друзей" можно перегружать и унарные операторы. Но это потребует от программиста дополнительных усилий. Для начала мысленно вернемся к исходной версии перегруженного оператора "++", определенной для класса three_d и реализованной в виде функции-члена. Для удобства приведем код этой операторной функции здесь.
// Перегрузка префиксной формы оператора "++".
three_d three_d::operator++()
{
х++;
у++;
z++;
return *this;
}
Как вы знаете, каждая функция-член получает (в качестве неявно переданного) аргумент this, который является указателем на объект, вызвавший эту функцию. При перегрузке унарного оператора с помощью функции-члена аргументы явным образом не передаются вообще. Единственным аргументом, необходимым в этой ситуации, является неявный указатель на вызывающий объект. Любые изменения, вносимые в данные объекта, повлияют на объект, для которого была вызвана эта операторная функция. Следовательно, при выполнении инструкции х++ (в предыдущей функции) будет инкрементирован член х вызывающего объекта.
В отличие от функций-членов, функции-не члены (в том числе и "друзья" класса) не получают указатель this и, следовательно, не имеют доступа к объекту, для которого они были вызваны. Но мы знаем, что "дружественной" операторной функции операнд передается явным образом. Поэтому попытка создать операторную функцию-"друга" operator++() в таком виде успехом не увенчается.
// ЭТОТ ВАРИАНТ РАБОТАТЬ НЕ БУДЕТ
three_d operator++(three_d op1)
{
op1.x++;
op1.y++;
op1.z++;
return op1;
}
Эта функция неработоспособна, поскольку только копия объекта, активизировавшего вызов функции operator++(), передается функции через параметр op1. Таким образом, изменения в теле функции operator++() не повлияют на вызывающий объект, они изменяют только локальный параметр.
Если вы хотите для перегрузки операторов инкремента или декремента использовать функцию-"друга", необходимо передать ей объект по ссылке. Поскольку ссылочный параметр представляет собой неявный указатель на аргумент, то изменения, внесенные в параметр, повлияют и на аргумент. Применение ссылочного параметра позволяет функции успешно инкрементировать или декрементировать объект, используемый в качестве операнда.
Если для перегрузки операторов инкремента или декремента используется функция-"друг", ее префиксная форма принимает один параметр (который и является операндом), а постфиксная форма — два параметра (вторым является целочисленное значение, которое не используется).
Ниже приведен полный код программы обработки трехмерных координат, в которой используется операторная функция-"друг" operator++(). Обратите внимание на то, что перегруженными являются как префиксная, так и постфиксная формы операторов инкремента.
// В этой программе используются перегруженные
// операторные функции-"друзья" operator++() .
#include <iostream>
using namespace std;
class three_d {
int x, y, z; // 3-мерные координаты
public:
three_d() { x = у = z = 0; }
three_d(int i, int j, int k) {x = i; у = j; z = k; }
friend three_d operator+(three_d op1, three_d op2);
three_d operator=(three_d op2);
// Эти функции для перегрузки
// оператора "++" используют ссылочные параметры.
friend three_d operator++(three_d &op1);
friend three_d operator++(three_d &op1, int notused);
void show();
};
// Теперь это функция-"друг".
three_d operator+(three_d op1, three_d op2)
{
three_d temp;
temp.x = op1.x + op2.x;
temp.у = op1.у + op2.y;
temp.z = op1.z + op2.z;
return temp;