У меня есть идея использования слова 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));
}
};
Какая выгода может стать перегрузкой оператора — как друга?
Я действительно не понимаю, почему кого-то это может заинтересовать.
Я много читал об этом, но не получил ясного представления.
Может ли кто-нибудь написать небольшой пример, где я могу наблюдать за фактом?
Взгляни на Херб Саттерс и пример Скотта Мейерса:
Вот резюме:
Во-первых: сделать операторы похожими — не членами: если вы выполняете c = a — b, к какому объекту принадлежит минус? стоит? б? или нет. Большинство людей согласны ни с кем, следовательно, не является членом.
Второе: операторы должны изменить частный контент, таким образом, вы либо заводите друзей, либо используете функции доступа, такие как геттеры. Так что большинство людей придерживаются друга.
В вашем конкретном примере сразу за объявлением друга следует определение, которое является наиболее компактным способом определения Глобальный функция друга.
Когда операторная функция реализована как функция-член, крайний левый (или
только) операнд должен быть объектом (или ссылкой на объект) класса оператора. Если
левый операнд должен быть объектом другого класса или фундаментального типа, эта операторная функция
должен быть реализован как функция, не являющаяся членом (например, при перегрузке <<
а также >>
как операторы вставки и извлечения потока соответственно).
Не являющаяся членом операторная функция может быть сделана friend
класса, если эта функция
должен получить доступ private
или же protected
члены этого класса напрямую. Функции-члены оператора определенного класса вызываются (неявно компилятором) только в том случае, когда левый операнд двоичного оператора является конкретно объектом этого класса или когда единственный операнд унарного оператора является объектом этого класса.
Другой причиной, по которой вы можете выбрать функцию, не являющуюся членом, для перегрузки оператора, является
позволить оператору быть коммутативной.
Например, предположим, у нас есть переменная основного типа, number
типа long int
и объект bigInteger1
из класса HugeInteger
(класс, в котором целые числа могут быть произвольно большими, а не ограничиваться размером машинного слова базового оборудования). Оператор вычитания (-
) производит временный HugeInteger
объект как разница HugeInteger
и long int
(как в выражении bigInteger1 - number
), или как разница long int
и HugeInteger
(как в выражении number - bigInteger1
). Таким образом, мы требуем, чтобы оператор вычитания был коммутативной (точно так же, как это с двумя операнды фундаментального типа). Проблема в том, что объект класса должен появиться на оставил оператора вычитания, если этот оператор должен быть перегружен как функция-член. Таким образом, мы также перегружаем оператор как функцию, не являющуюся членом, чтобы позволить HugeInteger
появиться справа от вычитания. operator-
функция, которая имеет дело с HugeInteger
слева все еще может быть функция-член. Функция, не являющаяся членом, может просто поменять свои аргументы и вызвать функцию-член.