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

После создания класса его название становится новым типом данных. Тем самым пользовательские классы расширяют возможности языка C++. С помощью перегрузки операторов можно еще больше расширить возможности объектов, т. к. перегрузка операторов позволяет экземплярам классов участвовать в обычных выражениях. Например, перегрузив оператор + можно сложить объект с другим объектом или любым элементарным типом данных.

Способы перегрузки операторов

Перегрузка операторов производится с помощью методов, имеющих специальные названия. Определив в классе «операторный» метод можно изменить поведение оператора по своему вкусу. Например, перегрузив оператор + можно вместо сложения производить вычитание. Однако пользователи класса вряд ли положительно оценят такую инициативу. Тем не менее, в некоторых случаях изменение смысла оператора довольно полезно. Например, класс cout перегружает оператор побитового сдвига << для вывода данных в окно консоли.

Выполнить перегрузку операторов можно тремя способами:

  • с помощью «операторного» метода:
  • с помощью дружественной функции;
  • с помощью обычной функции.

Перегрузка с помощью «операторного» метода

«Операторный» метод имеет следующий формат:

<Тип результата> operator<Название оператора>(
     [<Тип> <Название параметра1>[, ..., <Тип> <Название параметраN>]])
{
   // Тело метода
}

Название «операторного» метода состоит из слова operator, после которого указывается перегружаемый оператор, например, operator+, operator- и т. д. Внутри круглых скобок указывается тип, объект которого может быть расположен в выражении справа от перегружаемого оператора. Следовательно, для каждого типа, с которым может взаимодействовать экземпляр класса внутри выражения, необходимо создать отдельный «операторный» метод. Например, чтобы сложить объект с целым числом следует создать метод operator+(int x), а для сложения с вещественным числом — метод operator+(double x). Внутри метода доступен указатель this на объект, который расположен слева от оператора. Таким образом, внутри метода можно напрямую обращаться к атрибутам и методам класса. Пример перегрузки оператора + для сложения объекта с целым числом и возвратом нового объекта:

C C::operator+(int x) {     // Объект класса C + целое число
   C newobj;                // Создаем временный объект
   newobj.x_ = x_ + x;      // x_ - закрытый член класса C
   return newobj;           // Возвращаем временный объект
}

Метод будет вызван в такой ситуации:

C obj1(10), obj2;
obj2 = obj1 + 20;
std::cout << obj2.getX() << std::endl; // 30

Однако, если будет следующая ситуация, то метод вызван не будет, т. к. объект должен быть расположен слева от оператора, а не справа:

obj2 = 20 + obj1;           // Метод C::operator+(int x) не вызывается!

Перегрузить оператор + в этом случае позволяют дружественные функции.

Перегрузка с помощью дружественной функции

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

friend C operator+(int x, C &obj);

Пример определения дружественной функции вне класса:

C operator+(int x, C &obj) {      // Целое число + объект класса C
   C newobj;
   newobj.x_ = obj.x_ + x;        // Обращение к x_ через параметр
   return newobj;
}

С помощью дружественной функции можно также заменить «операторный» метод. Тем не менее, стоит отдать предпочтение «операторным» методам, а дружественные функции применять в случаях, когда обойтись методом нельзя. В качестве примера перегрузим оператор + для сложения объекта с целым числом:

C operator+(C &obj, int x) {      // Объект класса C + целое число
   C newobj;
   newobj.x_ = obj.x_ + x;
   return newobj;
}

Если мы хотим, чтобы в выражении слева и справа от объекта могли быть расположены целые числа:

C obj1(10), obj2;
obj2 = 10 + obj1 + 5;
std::cout << obj2.getX() << std::endl; // 25

то при объявлении типа параметра нужно дополнительно указать ключевое слово const:

friend C operator+(int x, const C &obj);
friend C operator+(const C &obj, int x);

Перегрузка с помощью обычной функции

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

// Обычная функция
C operator+(const C &obj, int x) { // obj2 = obj1 + 5;
   return C(obj.getX() + x);
}

Доступа к закрытому полю x_ внутри функции нет, поэтому для получения значения поля используется общедоступный метод getX(), а для изменения значения — конструктор класса C. Т. к. мы объявили параметр obj константным, то внутри функции доступа к обычным методам не будет, только к общедоступным константным методам:

int getX() const { return x_; }

Если ключевое слово const при объявлении параметра в функции operator+() убрать, то будет доступ ко всем общедоступным методам.

Ограничения

При перегрузке операторов следует учитывать, что:

  • с помощью дружественных и обычных функций нельзя перегрузить операторы =, (), -> и []. Для перегрузки этих операторов нужно использовать «операторные» методы;
  • вообще нельзя перегрузить операторы . (точка), ::, ?: и .*;
  • нельзя изменить приоритет операторов;
  • нельзя изменить количество параметров в «операторном» методе (исключением является перегрузка оператора ()) или дружественной «операторной» функции;
  • нельзя использовать значения по умолчанию в параметрах (исключением является перегрузка оператора ());
  • нельзя добавить новые операторы.

Учебник C++ (Qt Creator и MinGW)
Учебник C++ (Qt Creator и MinGW) в формате PDF

Помощь сайту

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов