перегрузка оператора c++

При перегрузке операторов необходимо перегружать >= ‹= и !=?

Кажется, что для С++ было бы разумно вызывать !operator= для !=, !> для operator‹= и !‹ для operator>=.

Так ли это, или необходимо перегружать каждую функцию?


person finiteloop    schedule 06.02.2010    source источник


Ответы (9)


Да, это необходимо, если вы хотите, чтобы все они работали так, как вы хотите, чтобы они работали.

C++ не навязывает какую-либо конкретную семантику большинству перегружаемых операторов. Единственное, что исправлено, — это общий синтаксис оператора (включая унарность или бинарность, а также такие вещи, как приоритет и ассоциативность). Это сразу означает, что реальная функциональность, которую вы реализуете в своей перегрузке, может быть абсолютно произвольной. В общем случае может не быть никакой значимой связи между тем, что делает оператор ==, и тем, что делает оператор !=. Оператор == может записывать данные в файл, а оператор != может сортировать массив.

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

person AnT    schedule 06.02.2010
comment
Ваш пример для == и != довольно надуманный. Более реалистичным был бы класс, представляющий объект SQL, где вам приходится иметь дело со специальной семантикой NULL. - person dan04; 02.07.2010

операторы Boost могут быть что ты ищешь. Они выведут большинство ваших операторов на основе нескольких фундаментальных.

То, что С++ не обеспечивает это автоматически, имеет смысл, поскольку, например, можно было бы придать совершенно разные значения ‹ и > (хотя часто это было бы плохой идеей).

person small_duck    schedule 06.02.2010
comment
С++ предоставляет это как std::rel_ops, но его сложно использовать правильно и, возможно, короче, если вместо этого просто ввести их самостоятельно (избегая путаницы). - person ; 07.02.2010

Я собираюсь принять точку зрения меньшинства здесь. Если вы уже используете boost, то использование операторов boost не так уж и сложно. Это может быть правильным и проверенным способом сделать что-то, но добавление зависимости повышения только для операторов — это излишество.

Можно писать сложные программы на C++ без ускорения (что я лично нахожу эстетически неприятным), и поэтому Keep It Simple (глупо), чтобы ответить на вопрос ОП, если вы перегружаете operator ==, вы также должны перегружать operator != . То же самое верно для <, >, ++ и т. д.

person Igor Zevaka    schedule 06.02.2010
comment
Если вам по какой-либо причине не нравится ускорение, это не значит, что вы не можете использовать ту же технику. Мой ответ содержит ссылку на один автономный заголовок, который я написал в качестве примера того, как именно это сделать в этом случае. - person ; 07.02.2010
comment
Я просто отвечаю на вопрос - С++ не вызывает автоматически operator == и не инвертирует результат, когда != не определено. Не спорю, что есть автоматический способ сделать это. - person Igor Zevaka; 07.02.2010

Нет, вам нужно только перегрузить оператор == и оператор ‹, об остальном позаботится стандартная библиотека :)

(EDIT: см. использование пространства имен std::rel_ops;)

person James    schedule 06.02.2010
comment
Не думайте, что это так... Если бы это было правдой, зачем на этой странице приводить пример определения != в терминах ==? cs.caltech.edu/courses/cs11/ материал/cpp/донни/cpp-ops.html - person H. Green; 07.02.2010
comment
Нет, вы должны явно определить каждый оператор. - person Igor Zevaka; 07.02.2010
comment
@Autopulated: одной директивы using недостаточно, вам нужны отдельные объявления using для каждого оператора, чтобы ввести имена в пространство имен, чтобы их можно было найти через ADL. - person ; 07.02.2010

Да, необходимо перегружать любые операторы, которые вы хотите использовать, как вы их определяете - C++ не примет решение, которое вы описали выше; однако имейте в виду, что если причиной перегрузки является сортировка вашего класса, вам нужно только переопределить операторы, используемые процедурой сортировки. В случае алгоритма сортировки RTL вам нужно переопределить только ‹ и =.

person fupsduck    schedule 07.02.2010

Да! Это технически разные операторы. Компиляторы C++ по своей сути не являются механизмами вывода, они являются синтаксическими анализаторами/компиляторами. Они сделают ровно столько, сколько вы скажете. http://www.parashift.com/c++-faq-lite/operator-overloading.html, http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B

person H. Green    schedule 06.02.2010
comment
За исключением того, что они являются двигателями вывода! Посмотрите на ADL и выясните правила разрешения перегрузки функций для хорошей долгой головной боли. - person ; 07.02.2010
comment
Я подозреваю, что многие исследователи ИИ не согласятся с вами в техническом определении механизма логического вывода в информатике. Но да, то, что могут понять современные компиляторы, впечатляет. - person H. Green; 07.02.2010
comment
Определение, которое я использую: механизм вывода — это форма конечного автомата, состоящая из трех действий: сопоставление, выбор и выполнение правил. Правила представляют собой просто комбинацию разрешения перегрузки функций и объявлений функций и типов в программе. Не спорю, что примитивно, конечно. - person ; 07.02.2010

Есть несколько горячих клавиш, которые вы можете использовать, например как CRTP, чтобы получать их автоматически добавлено (см. различные классы сравнения) в ваш класс.

person Community    schedule 06.02.2010
comment
Интересно, почему за этот и теперь удаленный ответ stakx проголосовали против. - person GManNickG; 07.02.2010
comment
Удивительно, я давно перестал беспокоиться о репутации, но я все еще вижу, как люди играют в игры, пытаясь повлиять на ответы. - person ; 07.02.2010

C++ как язык не определяет какой-либо оператор в терминах любого другого перегруженного оператора. То, что у вас есть operator+, не означает, что вы получаете operator+= бесплатно (в отличие от Ruby и Scala). То, что у вас есть операторы < и ==, не означает, что вы получаете <= бесплатно. То, что у вас есть оператор ==, не означает, что вы получаете != бесплатно (в отличие от Ruby и Scala). То, что у вас есть унарный operator * (унарный), не означает, что вы получаете operator -> бесплатно.

std::relops (если они импортированы правильно) и предоставляют определения по умолчанию, а Boost предоставляет некоторые примеси, которые определяют все операторы сравнения с точки зрения < и ==.

person Ken Bloom    schedule 18.05.2010

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

person anjali gulati    schedule 18.05.2010