Используя знания относительно ссылочных переменных, теперь можно легко понять, как унарные операторы перегружаются с помощью дружественных функций. Для начала вернемся к исходной версии оператора ++ по отношению к классу three_d. Для удобства он представлен ниже:
// перегрузка унарного оператора
three_d three_d::operator++ ()
{
х++;
у++;
z++;
return *this;
}
Как известно, всякая функция-член имеет неявный аргумент, соответствующий ключевому слову this и являющийся указателем на объект, членом которого служит данная функция. По этой причине при перегрузке унарного оператора с помощью функции-члена нет необходимости для этой функции иметь какие-либо аргументы. Единственным необходимым аргументом в такой ситуации является указатель на объект, осуществляющий вызов функции-оператора. Поскольку this является указателем на объект, то любые изменения данных объекта влияют на объект, вызывающий функцию-оператор. В отличие от этого функции-друзья не получают указателя this и поэтому не могут ссылаться на объект, вызывающий их. Таким образом, попытка создать дружественную функцию operator++() указанным ниже способом оказывается неудачной:
// HE РАБОТАЕТ
three_d operator++(three_d op1)
{
op1.x++;
op1.y++;
op1.z++;
return op1;
}
Эта функция не работает потому, что вызов функции-оператора operator++() осуществляется копией объекта, а не самим объектом op1. Поэтому изменения, которые претерпевает объект внутри operator++(), не влияют на исходный объект. Для того, чтобы выполнить перегрузку унарных операторов ++ или -- с помощью функции-друга, необходимо использовать параметр ссылочного типа. В таком случае копия не создается и действия производятся непосредственно с объектом, передаваемым функции. Ниже представлена полная программа, реализующая перегрузку оператора ++ с помощью дружественной функции:
// данная версия использует дружественную функцию operator++ ()
#include <iostream.h>
class three_d {
int x, y, z; // трехмерные координаты
public:
friend three_d operator+(three_d op1, three_d op2);
three_d operator= (three_d op2); // op1 подразумевается
// использование ссылки для перегрузки ++
friend three_d operator++(three_d &op1);
void show();
void assign (int mx, int my, int mz);
};
// дружественная функция
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;
}
// перегрузка =
three_d three_d::operator= (three_d op2)
{
x = op2.x; // целочисленное присваивание
у = op2.y; //и в данном случае = сохраняет
z = op2.z; // первоначальное значение
return *this;
}
/* перегрузка унарного оператора с помощью дружественной функции, необходимо использовать ссылочный параметр */
three_d operator++(three_d &op1)
{
op1.х++;
op1.y++;
op1.z++;
return op1;
}
// вывод координат X, Y, Z
void three_d::show ()
{
cout << x << ", ";
cout << у << ", ";
cout << z << "\n";
}
/ / присвоение координат
void three_d::assign (int mx, int my, int mz)
{
x = mx;
у = my;
z = mz;
}
int main()
{
three_d a, b, c;
a.assign(1, 2, 3);
b.assign(10, 10, 10);
a.show ();
b.show();
с = a+b; // сложение а и b
c.show();
с = a+b+c; // сложение a, b и с
с.show();
с = b = a; // демонстрация множественного присваивания
с.show();
b.show();
++c; // увеличение с
c.show();
return 0;
}
ПАМЯТКА: Для перегрузки операторов следует пользоваться функциями-членами. Функции-друзья предназначаются в С++ большей частью для специальных ситуаций. |