Перегрузка операторов как друга

У меня есть идея использования слова friend для доступа к закрытым членам помимо собственного класса. Например, у меня есть класс A, и мне нужно получить доступ к частному методу атрибута класса B внутри метода A. Я мог бы объявить метод как друг.

Однако см. следующий код:

#include <cstdlib>

class Coord {
  private:
    int x, y;
  public:
    Coord (int i1, int i2) : x(i1), y(i2) {
    }
    friend Coord operator- (Coord const& c1, Coord const& c2) {
        return Coord(c1.x-c2.x, c1.y-c2.y);
    }
    Coord abs() {
        return Coord(std::abs(x),std::abs(y));
    }
};

Какой выгодой может стать перегрузка оператора- как друга? Я действительно не понимаю, почему это может кого-то заинтересовать.

Я много читал об этом, но я не получил ясного представления.

Может ли кто-нибудь написать небольшой пример, где я могу наблюдать за фактом?


person dmayola    schedule 08.12.2012    source источник


Ответы (2)


Взгляните на Херба Саттерса и Скотта Пример Мейерса:

Вот резюме:

Во-первых: сделайте операторы вроде - не членами: если вы выполните c = a - b, к какому объекту относится минус? а? б? или нет. Большинство людей не согласны ни с кем, следовательно, не являются членами. Во-вторых: операторам необходимо изменить приватный контент, поэтому либо вы заводите друга, либо используете функции доступа, такие как геттеры. Поэтому большинство людей придерживаются друга.

В вашем конкретном примере за объявлением друга сразу следует определение, которое является наиболее компактным способом определения глобальной функции друга.

person Martin    schedule 08.12.2012

Когда операторная функция реализована как функция-член, крайний левый (или единственный) операнд должен быть объектом (или ссылкой на объект) класса оператора. Если левый операнд должен быть объектом другого класса или фундаментального типа, эта операторная функция должна быть реализована как функция, не являющаяся членом (например, при перегрузке << и >> в качестве операторов вставки и извлечения потока соответственно).

Функцию оператора, не являющуюся членом, можно сделать friend класса, если эта функция должна напрямую обращаться к private или protected членам этого класса. Функции-члены оператора определенного класса вызываются (неявно компилятором) только тогда, когда левый операнд бинарного оператора является объектом этого класса или когда единственный операнд унарного оператора является объектом этого класса.

Другая причина, по которой вы можете выбрать функцию, не являющуюся членом, для перегрузки оператора, заключается в том, что оператор должен быть коммутативным.

Например, предположим, что у нас есть переменная фундаментального типа, number, типа long int, и объект bigInteger1, класса HugeInteger (класс, в котором целые числа могут быть произвольно большими, а не ограничиваться машинным словом размер основного оборудования). Оператор вычитания (-) создает временный объект HugeInteger как разность HugeInteger и long int (как в выражении bigInteger1 - number) или как разность long int и HugeInteger (как в выражении number - bigInteger1). Таким образом, мы требуем, чтобы оператор вычитания был коммутативным (точно так же, как и с двумя операндами фундаментального типа). Проблема в том, что объект класса должен находиться слева от оператора вычитания, если этот оператор должен быть перегружен как функция-член. Итак, мы также перегружаем оператор как функцию, не являющуюся членом, чтобы HugeInteger отображалось справа от вычитания. Функция operator-, которая имеет дело с HugeInteger слева, все еще может быть функцией-членом. Функция, не являющаяся членом, может просто поменять местами свои аргументы и вызвать функцию-член.

person akaHuman    schedule 08.12.2012