Введение в перегрузку операторов
Часть раздела Объектно-ориентированное программирование путешествия по C++ на Coddy — урок 40 из 104.
Перегрузка операторов позволяет вам определить, как операторы, такие как +, - или ==, ведут себя при использовании с вашими пользовательскими классами. Вместо вызова методов вроде a.add(b) вы можете писать более интуитивно понятное a + b.
В C++ операторы — это, по сути, функции со специальными именами. Чтобы перегрузить оператор, вы определяете функцию, используя ключевое слово operator, за которым следует символ:
class Vector2D {
double x, y;
public:
Vector2D(double x, double y) : x(x), y(y) {}
// Перегрузка оператора +
Vector2D operator+(const Vector2D& other) const {
return Vector2D(x + other.x, y + other.y);
}
};Теперь вы можете складывать два вектора естественным образом:
Vector2D v1(1.0, 2.0);
Vector2D v2(3.0, 4.0);
Vector2D v3 = v1 + v2; // Вызывает v1.operator+(v2)Не все операторы могут быть перегружены. Оператор разрешения области видимости ::, доступ к членам ., тернарный оператор ?: и sizeof не могут быть перегружены. Кроме того, вы не можете создавать новые операторы или изменять приоритет операторов — * всегда будет вычисляться перед +.
Операторы могут быть реализованы как функции-члены (как показано выше) или как функции, не являющиеся членами. В следующих уроках вы узнаете, когда использовать каждый из подходов и как перегружать определенные категории операторов.
Задание
ЛегкоДавайте создадим класс Point, который представляет собой 2D-координату и поддерживает сложение двух точек с помощью оператора +. Это ваш первый шаг в перегрузку операторов — возможность заставить ваши собственные классы работать с привычными операторами.
Вы создадите два файла для организации вашего кода:
Point.h: Определите классPoint, который хранит координаты x и y (обе типаint). Ваш класс должен содержать:- Приватные члены для координат x и y
- Конструктор, принимающий значения x и y
- Геттеры
getX()иgetY()(оба const) - Перегруженный оператор
+, который складывает две точки и возвращает новый объектPointс комбинированными координатами
Оператор
+должен быть реализован как функция-член, которая принимает другой объектPointпо константной ссылке и возвращает новыйPoint. Пометьте его какconst, так как он не изменяет ни один из операндов.main.cpp: Считайте четыре целых числа из входных данных (x1, y1, x2, y2 на отдельных строках), представляющих две точки. Создайте два объектаPoint, сложите их с помощью оператора+и выведите результаты.Формат вывода:
Point 1: (<x1>, <y1>) Point 2: (<x2>, <y2>) Sum: (<sum_x>, <sum_y>)
Ключевая идея здесь заключается в том, что выражение p1 + p2 на самом деле вызывает p1.operator+(p2) за кулисами. Ваш перегруженный оператор позволяет писать интуитивно понятный код, такой как Point p3 = p1 + p2;, вместо чего-то вроде Point p3 = p1.add(p2);.
Преобразуйте входные строки в целые числа с помощью std::stoi(). Не забудьте про guard-включения (header guards) в вашем заголовочном файле.
Шпаргалка
Перегрузка операторов позволяет вам определять, как операторы, такие как +, - или ==, ведут себя с пользовательскими классами, обеспечивая интуитивно понятный синтаксис, такой как a + b вместо a.add(b).
Чтобы перегрузить оператор, определите функцию, используя ключевое слово operator, за которым следует символ:
class Vector2D {
double x, y;
public:
Vector2D(double x, double y) : x(x), y(y) {}
// Перегрузка оператора +
Vector2D operator+(const Vector2D& other) const {
return Vector2D(x + other.x, y + other.y);
}
};Использование:
Vector2D v1(1.0, 2.0);
Vector2D v2(3.0, 4.0);
Vector2D v3 = v1 + v2; // Вызывает v1.operator+(v2)Некоторые операторы нельзя перегружать: ::, ., ?: и sizeof. Вы не можете создавать новые операторы или изменять приоритет операторов.
Операторы могут быть реализованы как функции-члены или функции, не являющиеся членами класса.
Попробуйте сами
#include <iostream>
#include <string>
#include "Point.h"
using namespace std;
int main() {
// Чтение входных данных
string line1, line2, line3, line4;
getline(cin, line1);
getline(cin, line2);
getline(cin, line3);
getline(cin, line4);
int x1 = stoi(line1);
int y1 = stoi(line2);
int x2 = stoi(line3);
int y2 = stoi(line4);
// TODO: Создайте два объекта Point, используя входные значения
// TODO: Сложите две точки вместе, используя оператор +
// TODO: Выведите результаты в требуемом формате:
// Point 1: (<x1>, <y1>)
// Point 2: (<x2>, <y2>)
// Sum: (<sum_x>, <sum_y>)
return 0;
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыСборка и компиляция C++Заголовочные файлы и файлы исходного кодаПространства имен и область видимостиВведение в ООП на C++Классы и объектыУказатель 'this'Методы (функции-члены)Атрибуты (члены данных)Основы конструкторов и деструкторовИтоги — Простой калькулятор4Свойства классов
Члены экземпляра против статическихГеттеры и сеттерыКонстантные функции-членыКлючевое слово mutableСтатические методы и переменныеДружественные функции и классыИтоги — Менеджер банковских счетов7Наследование
Основы наследованияУровни доступа при наследованииПорядок вызова конструкторов и деструкторовПереопределение методовВиртуальные функции и VTableМножественное наследованиеВиртуальное наследованиеИтоги — Иерархия сотрудников10Обзор STL
Обзор и философия STLКонтейнеры STLИтераторыАлгоритмы STLФункторы и лямбда-выраженияИтоги: частота слов13Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonFactory и Abstract FactoryПаттерн BuilderПаттерн ObserverПаттерн Strategy2Управление памятью
Стек и кучаУказатели и ссылкиДинамическая память (new/delete)Умные указатели в C++RAII в C++Итоги — Менеджер динамического массива5Инкапсуляция
Спецификаторы доступа в C++Спецификаторы доступа: подробный разборСокрытие данныхStruct против ClassВложенные и внутренние классыИтоги — Система учета студентов8Полиморфизм
Полиморфизм компиляции и времени выполненияПерегрузка функцийВиртуальные функции: повторениеЧистые виртуальные функцииАбстрактные классыПроектирование интерфейсов на C++Dynamic Casting и RTTIИтоги: Калькулятор фигур11Продвинутые концепции ООП
Композиция против наследованияМиксины через CRTPИдиома PimplСтирание типовEnum Classes и строгая типизацияОбработка исключений в ООППользовательские иерархии исключений14Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикRAII как паттерн3Конструкторы и деструкторы
Конструктор по умолчаниюПараметризованный конструкторКонструктор копированияКонструктор перемещенияСписки инициализации конструктораДелегирующие конструкторыГлубокое погружение в деструкторыПравило трех / пяти / нуляПовторение — класс String6Перегрузка операторов
Введение в перегрузку операторовПерегрузка арифметических операторовПерегрузка операторов сравненияОператоры потоковПерегрузка оператора присваиванияПерегрузка операторов [] и ()Операторы преобразования типовИтоги — класс Matrix9Шаблоны
Шаблоны функцийШаблоны классовСпециализация шаблоновВариативные шаблоныОсновы SFINAE и Type TraitsИтоги — Обобщенный контейнер