§ 3. Перегрузка операций
3.1. Перегрузка арифметических операций
Перегрузка операторов в программировании — один из способов реализации полиморфизма. Она позволяет использовать нескольких различных вариантов применения оператора. Операторы имеют одно и то же имя, но различаются типами параметров, к которым они применяются. В языке C++ операторы реализованы в виде функций. Используя перегрузку функции оператора, вы можете определить свои собственные версии операторов, которые будут работать с разными типами данных, включая классы. С перегруженными операторами вы уже работали. В классе string перегружены операторы сравнения и оператор «+». Для сравнения строк используются те же знаки, что и для сравнения чисел, однако сравнение строк выполняется не так, как сравниваются числа. Сложение строк также имеет смысл, отличный от сложения чисел. Большинство операций в С++ можно перезагрузить (пример 3.1)[1]. Важно помнить, что перегрузка расширяет возможности языка, а не изменяет язык. Поэтому нельзя перегружать операторы для встроенных типов данных. Нельзя менять приоритет выполнения операторов и их ассоциативность (слева направо или справа налево). Нельзя создавать собственные операторы и перегружать некоторые встроенные (пример 3.2). Синтаксис перегрузки операций: тип operator @ (список_параметров-операндов) где @ — знак перегружаемой операции, тип — тип возвращаемого значения. Перегружать можно только операции, для которых хотя бы один аргумент представляет тип данных, определенный пользователем (например, класс). Функция для перегрузки операции должна быть определена либо как функция-член класса (пример 3.3), либо как внешняя функция, но дружественная классу (пример 3.4). Один и тот же оператор можно перегрузить несколько раз. Если бинарная[2] операция перегружается с использованием метода класса, то первым операндом она получает переменную класса, которая неявно передается через указатель this на объект. Вторым операндом является аргумент функции. Таким образом, бинарная операция, перегружаемая методом класса, имеет фактически один параметр (правый операнд), а левый передается неявно через указатель this. Если перегрузка бинарной операции реализована с использованием дружественной функции, то в списке параметров должно быть два аргумента. Пример 3.5. Вектор на плоскости задается парой координат. Описать класс Vect для представления вектора на плоскости. Реализовать метод, вычисляющий длину вектора, перегрузить операторы «+» (сложение двух векторов), «*» (умножения вектора на число), «==» (сравнение векторов), «>» (сравнение векторов по длине). Этапы выполнения задания 1. Полями класса будут координаты (x, y) вектора на плоскости. 2. Для вычисления длинны вектора в методе класса dl используется формула вычисления длины отрезка. 3. Реализовать перегрузку операций.
Любой перегруженный оператор можно вызвать с использованием функциональной формы записи (функции-операции): Vect v3 = operator + (v1, v2); Использование операции — это всего лишь сокращенная запись явного вызова функции операции. Поскольку функция-операция описывается так же, как любая другая функция, то и вызываться она может аналогично. Прямоугольную таблицу с числами в математике называют матрицей. Размер матрицы определяется количеством строк и столбцов в ней. Для матриц определены арифметические операции. Матрицу можно умножить на число — для этого каждый элемент матрицы умножается на него. Две матрицы одинакового размера можно сложить или отнять. Действия выполняются над элементами, стоящими на соответствующих местах. Пример 3.6. Описать класс Matrix. Перегрузить операции сложения, вычитания и умножения матрицы на число. Этапы выполнения задания 1. Полями класса будут целые числа m, n — количество строк и столбцов в матрице и двумерный вектор для хранения самой матрицы. 2. Реализовать метод rand_data, который будет заполнять матрицу случайными числами. 3. Перегрузка операций аналогична перегрузке операций, которые реализованы в примере 3.4.
[1] Более подробно о перегрузке операторов можно почитать, например здесь: https://habr.com/ru/post/489666/ [2] Операция является бинарной, если для ее выполнения необходимы два операнда. Например, операция сложения (a + b). Операция с одним операндом является унарной. Например, операция смены знака у числа (-a). |
Необходимость в перегрузке операций обусловлена потребностью описывать и применять к созданным программистом типам данных операции, по смыслу эквивалентные уже имеющимся в языке. Для реализации перегрузки операций в языке программирования необходимо ввести в нем соответствующие синтаксические конструкции. Вариантов реализации может быть много, однако они мало чем отличаются друг от друга. Достаточно помнить, что запись вида <операнд1> <знакОперации> <операнд2> аналогична вызову функции <знакОперации>(<операнд1>,<операнд2>). Если разрешить программисту описывать поведение операторов в виде функций, то проблема перегрузки операторов будет решена. Пример 3.1. Операции, которые можно перегрузить в С++:
Пример 3.2. Операции, которые нельзя перегрузить в С++:
Дружественная функция — это функция, не являющаяся членом класса, но имеющая доступ к его закрытым членам. Ею может быть как обычная функция, так и метод другого класса. Для объявления дружественной функции используется ключевое слово friend перед объявлением функции, которая станет дружественной классу. Функция может быть объявлена как в разделе public, так и разделе private. Пример 3.3. Перегрузка операции «+» с применением метода класса:
Пример 3.4. Перегрузка операции «+» с применением внешней функции, дружественной классу:
Пример 3.5. Программа.
Результат работы: Роб Мюррей, в своей книге «C++ Strategies and Tactics» рекомендовал перегружать унарные операции и операции, совмещенные с присваиванием (+=, *= и др.), как члены класса. Бинарные операции он рекомендовал перегружать с использованием дружественных функций.
Пример 3.6. Описание класса Matrix.
|