Menu
Coddy logo textTech

Перегрузка арифметических операторов

Часть раздела Объектно-ориентированное программирование путешествия по C++ на Coddy. Урок 41 из 104.

Арифметические операторы, такие как +, -, * и /, обычно перегружаются, чтобы пользовательские классы вели себя подобно встроенным числовым типам. Эти операторы обычно возвращают новый объект, а не изменяют операнды.

Вот класс Fraction с арифметическими операторами:

class Fraction {
    int numerator, denominator;
    
public:
    Fraction(int n, int d) : numerator(n), denominator(d) {}
    
    Fraction operator+(const Fraction& other) const {
        return Fraction(
            numerator * other.denominator + other.numerator * denominator,
            denominator * other.denominator
        );
    }
    
    Fraction operator*(const Fraction& other) const {
        return Fraction(numerator * other.numerator, 
                        denominator * other.denominator);
    }
};

Обратите внимание, что оба оператора помечены как const, поскольку они не изменяют ни один из операндов. Они создают и возвращают новый объект Fraction с результатом.

Для compound assignment операторов, таких как +=, шаблон отличается. Они изменяют левый операнд и возвращают ссылку на него:

Fraction& operator+=(const Fraction& other) {
    numerator = numerator * other.denominator + other.numerator * denominator;
    denominator = denominator * other.denominator;
    return *this;
}

Распространённая практика — реализовать базовый оператор через составное присваивание, уменьшая дублирование кода:

Fraction operator+(const Fraction& other) const {
    Fraction result = *this;    // Скопировать этот объект
    result += other;            // Использовать составное присваивание
    return result;
}

Этот подход гарантирует согласованность обоих операторов и упрощает сопровождение.

challenge icon

Задание

Легко

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

Вы создадите два файла, чтобы организовать свой код:

  • Money.h: определите класс Money, который хранит сумму в cents (как int), чтобы избежать проблем с точностью чисел с плавающей запятой. Ваш класс должен поддерживать:
    • конструктор, принимающий dollars и cents как отдельные целые числа
    • геттер getDollars(), возвращающий долларовую часть
    • геттер getCents(), возвращающий часть в cents (0–99)
    • перегруженные операторы + и -, возвращающие новый объект Money
    • перегруженные составные операторы присваивания += и -=, изменяющие текущий объект и возвращающие ссылку на него
    • метод display(), который выводит деньги в формате $X.YY (для cents всегда используются две цифры)

    Реализуйте базовые операторы (+ и -) через составные операторы присваивания, чтобы сократить duplication, как показано в уроке. Все арифметические операторы должны быть помечены как const, где это уместно.

  • main.cpp: считайте из input четыре целых числа, представляющих две денежные суммы (dollars1, cents1, dollars2, cents2 в отдельных строках). Создайте два объекта Money, затем продемонстрируйте работу всех операторов:
    • выведите "Amount 1: ", followed by первую отображённую сумму
    • выведите "Amount 2: ", followed by вторую отображённую сумму
    • сложите две суммы и выведите "Sum: ", followed by результат
    • вычтите вторую сумму из первой и выведите "Difference: ", followed by результат
    • используйте +=, чтобы прибавить вторую сумму к первой, затем выведите "After +=: ", followed by изменённую первую сумму

Для метода display() используйте std::setw(2) и std::setfill('0') из <iomanip>, чтобы cents всегда отображались двумя цифрами (например, $5.07, а не $5.7).

Преобразуйте строки input в целые числа с помощью std::stoi(). Не забудьте добавить защитные конструкции заголовка в файл заголовка.

Попробуйте сами

#include <iostream>
#include <string>
#include "Money.h"

using namespace std;

int main() {
    // Прочитать ввод для двух денежных сумм
    string line;
    
    getline(cin, line);
    int dollars1 = stoi(line);
    
    getline(cin, line);
    int cents1 = stoi(line);
    
    getline(cin, line);
    int dollars2 = stoi(line);
    
    getline(cin, line);
    int cents2 = stoi(line);
    
    // TODO: Создать два объекта Money с введёнными значениями
    
    // TODO: Вывести "Amount 1: " за которым следует отображение первой суммы
    
    // TODO: Вывести "Amount 2: " за которым следует отображение второй суммы
    
    // TODO: Сложить две суммы и вывести "Sum: " за которым следует результат
    
    // TODO: Вычесть вторую из первой и вывести "Difference: " за которым следует результат
    
    // TODO: Использовать += чтобы добавить вторую сумму к первой, затем вывести "After +=: " за которым следует изменённая первая сумма
    
    return 0;
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор C++