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

  Юрий  | 

  |

  Обновл. 13 Сен 2021  | 

 66700

 ǀ   16 

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

Например, перегрузим оператор равенства == и оператор неравенства != для класса Car:

Всё просто. Поскольку результат выполнения оператора != является прямо противоположным результату выполнения оператора ==, то мы определили оператор !=, используя уже перегруженный оператор == (уменьшив, таким образом, количество кода, сложность и возможность возникновения ошибок).

А как насчет операторов < и >? Здесь нужно определиться, чем один объект класса Car может быть лучше другого объекта класса Car, и как это всё выразить в коде. Неочевидно! Поэтому здесь мы и не перегружали операторы < и >.

Совет: Не перегружайте операторы, которые являются бесполезными для вашего класса.

Однако, операторы < и > можно использовать для сортировки списка автомобилей (объектов класса Car) в алфавитном порядке, используя члены m_company и m_model, поэтому всегда рассматривайте разные варианты.

Некоторые классы-контейнеры Стандартной библиотеки C++ требуют перегрузки оператора <, чтобы они могли сохранять отсортированные элементы.

Перегрузим операторы сравнения >, <, >= и <=:

Всё просто.

Но, как вы уже могли бы заметить, операторы > и <= являются логическими противоположностями, поэтому один из них можно было бы определить через второй. Та же ситуация и с < и >=. Но, поскольку определения функций перегрузки столь просты, а операторы в строке объявления функции так хорошо сочетаются с операторами в строке возврата результата, мы решили этого не делать.

Тест

Задание №1

Используя класс Dollars, приведенный выше, перепишите операторы < и <=, используя их логические противоположности.

Ответ №1

Задание №2

Добавьте перегрузку операторов << и < в класс Car, представленный выше, чтобы следующий фрагмент кода:

Выдавал следующий результат:

(Ford, Mustang)
(Ford, Ranger)
(Renault, Duster)
(Renault, Logan)

Ответ №2


Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (159 оценок, среднее: 4,90 из 5)
Загрузка...

Комментариев: 16

  1. Григорий лепс:

    А как перегрузить оператор равенства, чтобы все это работало вот в таком выражении в мэйне?

    С примитивными данными такой номер проходит:

    А вот со своим типом что-то не могу никак допетрить как перегрузить оператор?

    1. Владимир:

      Ответ в явных и неявных приведений типов.
      Для фундаментальных типов они есть.
      А для своих классов пиши их сам, компилятор не в курсе как твой класс конвертировать в bool.
      Разберем как твой пример видит компилятор:

      Компилятор его воспринимает следующим образом ((x==y)==z)
      x==y возвращает true, так как они равны, затем сравнивается true==z
      так как z это фундаментальный тип и он не равен 0 то он конвертируется в true и получается следующее,
      компилятор сравнивает true==true и возвращает true, ониж равны, все логично.

  2. Saliwer:

    Задание 1:
    Можно определить один оператор сравнения < или > и через него переопределить все остальные, например:

  3. Эвелина:

    Для меня отлично работает следующий вариант перегрузки оператора сравнения:

  4. kmish:

    Можно ли где-нить почитать как реализовано сравнение двух переменных типа std::string у оператора "<" ?
    Сначала сравниваются нулевые элементы, затем первые, вторые и т.д.?
    Или как-то по другому?

    1. Александр:

      С-строки сравниваются независимо от содержимого :))) сравниваются указатели

      std::string сравниваются лексикографически.

      Или, по простому, "По алфавиту".
      Т.е. да, сравниваются первые элементы (коды символов), если они равны, то вторые и т.д. до нахождения различия. Если различий нет, но одна из строк закончилась — значит она и есть "меньше".

      ЗЫ "по алфавиту" это очень условно… строчная 'a' будет "больше" заглавной 'A'. Сравнение идет именно по номерам символов

    2. Антон Каруна:

      автор 1 коммента прав, используется ascii таблица, где каждому символу char присвоен определенный порядковый номер

  5. subj:

    Мне иначе вот в голову взбрело написать:

    1. Валерий:

      Неправильно.
      Пример.
      Пара (AAA, ZZZ) должна быть меньше(AAAA, AA).
      А с учетом конкатенации AAAZZZ будет больше чем AAAAAA.

  6. Torgu:

    Тоже как вариант для оператора сравнения

    1. Валерий:

      Мой чемпион

      1. Александр:

        Не чемпион — компании отсортированы в обратном от верного варианте

  7. Герман:

    Не совсем ясно, как функция sort "подхватывает" оператор < для класса Car.

    1. Фото аватара Юрий:

      Функция sort является встроенным функционалом заголовочного файла vector, который вы подключаете. Можете детальнее поискать информацию о функции sort в Интернете.

      1. Александр:

        функция std::sort не имеет отношения к векторам. Она в заголовочном файле <algorythm> объявляется и работает со всеми контейнерами для которых определены итераторы, при этом для элементов контейнера должен быть определен оператор "меньше"

        Самый часто используемый синтаксис:
        std::sort(arr.begin(), arr.end()); — передаем указатель (итератор) на начало контейнера и терминальный указатель (итератор) (тот, который идет ЗА последним)
        для этой формы должен быть определен оператор "<" для элементов контейнера

        Можно без оператора "<":
        std::sort(arr.begin(), arr.end(), checker); — передаем дополнительно функцию-чекер, которая будет определять правила сортировки

        1. zashiki:

          аа…погуглила, checker это компаратор.
          Т.е. все эти дружественные функции сравнения в уроке — неявно конвертируются в компаратор при sort?

Добавить комментарий

Ваш E-mail не будет опубликован. Обязательные поля помечены *