Menu
Coddy logo textTech

Перегрузка операторов сравнения

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

Операторы сравнения, такие как ==, !=, <code><, , <= и >=, позволяют сравнивать объекты ваших пользовательских классов. Эти операторы возвращают bool и должны быть помечены как const, так как они не изменяют ни один из операндов.

class Date {
    int year, month, day;
    
public:
    Date(int y, int m, int d) : year(y), month(m), day(d) {}
    
    bool operator==(const Date& other) const {
        return year == other.year && 
               month == other.month && 
               day == other.day;
    }
    
    bool operator<(const Date& other) const {
        if (year != other.year) return year < other.year;
        if (month != other.month) return month < other.month;
        return day < other.day;
    }
};

Полезный прием заключается в реализации других операторов сравнения на основе тех, которые вы уже определили. Как только у вас появятся == и <code><, остальные последуют естественным образом:

bool operator!=(const Date& other) const {
    return !(*this == other);
}

bool operator>(const Date& other) const {
    return other < *this;
}

bool operator<=(const Date& other) const {
    return !(other < *this);
}

bool operator>=(const Date& other) const {
    return !(*this < other);
}

Этот подход сокращает дублирование кода и гарантирует согласованное поведение всех ваших операторов сравнения. Если вы позже измените принцип работы операторов равенства или «меньше чем», остальные операторы автоматически останутся синхронизированными.

challenge icon

Задание

Легко

Давайте создадим класс Version, который представляет номера версий программного обеспечения (например, 2.1.0 или 3.0.5) и поддерживает все шесть операторов сравнения. Это практический пример, где сравнение версий определяет, какое программное обеспечение является более новым — идеальный вариант для практики перегрузки операторов сравнения.

Вы создадите два файла для организации вашего кода:

  • Version.h: Определите класс Version, который хранит три целых числа, представляющих основной (major), дополнительный (minor) и корректировочный (patch) номера версий. Ваш класс должен поддерживать:
    • Конструктор, принимающий значения major, minor и patch
    • Геттеры для каждого компонента: getMajor(), getMinor(), getPatch() (все const)
    • Все шесть операторов сравнения: ==, !=, <, >, <=, >=
    • Метод toString(), который возвращает версию в виде строки в формате "major.minor.patch"

    Реализуйте == и < напрямую, а затем определите остальные четыре оператора через эти два. Для сравнения «меньше чем» сначала сравнивайте major, затем minor, если major равны, и затем patch, если и major, и minor равны. Все операторы сравнения должны быть константными функциями-членами (const member functions).

  • main.cpp: Считайте шесть целых чисел из входных данных, представляющих две версии (major1, minor1, patch1, major2, minor2, patch2 на отдельных строках). Создайте два объекта Version и сравните их, используя все ваши операторы.

    Формат вывода:

    Version 1: <v1>
    Version 2: <v2>
    v1 == v2: <true/false>
    v1 != v2: <true/false>
    v1 < v2: <true/false>
    v1 > v2: <true/false>
    v1 <= v2: <true/false>
    v1 >= v2: <true/false>

    Выводите true или false (в нижнем регистре) для каждого результата сравнения.

Ключевой прием здесь заключается в реализации четырех производных операторов (!=, >, <=, >=) с использованием только == и <. Это уменьшает дублирование кода и гарантирует согласованность всех операторов, если вы когда-нибудь измените логику сравнения.

Преобразуйте входные строки в целые числа с помощью std::stoi(). Используйте std::to_string() для создания строки версии. Не забудьте про guard-вставки (header guards) в вашем заголовочном файле.

Шпаргалка

Операторы сравнения (==, !=, <code><, , <=, >=) позволяют сравнивать объекты пользовательских классов. Эти операторы возвращают bool и должны быть помечены как const, так как они не изменяют ни один из операндов.

class Date {
    int year, month, day;
    
public:
    Date(int y, int m, int d) : year(y), month(m), day(d) {}
    
    bool operator==(const Date& other) const {
        return year == other.year && 
               month == other.month && 
               day == other.day;
    }
    
    bool operator<(const Date& other) const {
        if (year != other.year) return year < other.year;
        if (month != other.month) return month < other.month;
        return day < other.day;
    }
};

Реализуйте остальные операторы сравнения через == и <code><, чтобы уменьшить дублирование кода и обеспечить согласованность:

bool operator!=(const Date& other) const {
    return !(*this == other);
}

bool operator>(const Date& other) const {
    return other < *this;
}

bool operator<=(const Date& other) const {
    return !(other < *this);
}

bool operator>=(const Date& other) const {
    return !(*this < other);
}

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

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

using namespace std;

int main() {
    // Считать шесть целых чисел для двух версий
    string line;
    
    getline(cin, line);
    int major1 = stoi(line);
    
    getline(cin, line);
    int minor1 = stoi(line);
    
    getline(cin, line);
    int patch1 = stoi(line);
    
    getline(cin, line);
    int major2 = stoi(line);
    
    getline(cin, line);
    int minor2 = stoi(line);
    
    getline(cin, line);
    int patch2 = stoi(line);

    // TODO: Создать два объекта Version
    
    // TODO: Вывести Version 1 и Version 2, используя toString()
    
    // TODO: Сравнить, используя все шесть операторов, и вывести результаты
    // Используйте "true" или "false" (строчными буквами) для каждого сравнения
    // Формат: "v1 == v2: true" или "v1 == v2: false"
    
    return 0;
}
quiz iconПроверьте себя

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

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