Переопределение операторов с помощью дружественных функций
Механизм объявления дружественных функций часто используется при переопределении операторов.
Давайте вспомним, как раньше мы переопределяли операторы для класса _3d
class _3d
{
//...
_3d operator + (_3d b);
};
_3d _3d::operator + (_3d b)
{
_3d c;
c.x = x + b.x;
c.y = y + b.y;
c.z = z + b.z;
return c; }
А теперь посмотрим, как тот же самый оператор + можно переопределить с использованием дружественной функции.
class _3d
{
//...
friend _3d operator + (_3d &a, _3d &b);
};
_3d operator + (_3d &a, _3d &b)
{
_3d c;
c.x = a.x + b.x;
c.y = a.y + b.y;
c.z = a.z + b.z;
return c;
}
Давайте обсудим, в каких случаях для доступа к приватной части типов следует использовать элементы, а в каких - дружественные функции. Некоторые операции должны быть элементами - конструкторы, деструкторы и виртуальные функции, но, как правило, программист имеет возможность выбора.
При определении того, какой должна быть функция нужно руководствоваться простым правилом: операция, изменяющая состояние объекта класса, должна быть элементом, а не другом.
Все вышесказанное в полной мере относится и к способу переопределения операторов. Для операторов вроде "=", "++" и "+=" выражение слева ясно определено, и, по-видимому, естественно реализовать их как операции над объектом, обозначенным этим выражением. Напротив, если для всех операндов операции желательно иметь неявное преобразование, функция, реализующая его, должна быть дружественной, а не элементом. Часто именно так обстоит дело для функций, реализующих операторы "+", "-", "||" и др.
Например,
class X {...};
X x;
x=1+x; // т.е. x = 1.operator + (x); - ошибка
В этом случае использование функции элемента для переопределения оператора "+" в любом случае породит ошибку. Так что здесь было бы правильнее применять дружественную функцию.
Если преобразования типов не определяются, то, по-видимому, нет явных причин для предпочтения элемента дружественной функции. При прочих равных условиях, выбирайте элемент.
[назад] | [оглавление] | [вперед] |