Многие считают, что перегрузка операторов в C ++ является «плохой вещью» (tm), и это ошибка, которую нельзя повторять на более новых языках. Конечно, это была одна особенность, специально упущенная при разработке Java.
Теперь, когда я начал читать Scala, я обнаружил, что он имеет то, что очень похоже на перегрузку операторов (хотя технически у него нет перегрузки операторов, потому что у него нет операторов, только функции). Тем не менее, он не будет качественно отличаться от перегрузки операторов в C ++, где, насколько я помню, операторы определяются как специальные функции.
Поэтому мой вопрос заключается в том, что делает идею определения «+» в Scala лучшей идеей, чем в C ++?
c++
scala
operator-overloading
skaffman
источник
источник
Ответы:
C ++ наследует истинные синие операторы от C. Под этим я подразумеваю, что «+» в 6 + 4 очень особенный. Например, вы не можете получить указатель на эту + функцию.
Scala, с другой стороны, не имеет операторов таким образом. Он просто обладает большой гибкостью в определении имен методов, плюс немного встроенного приоритета для несловарных символов. Так что технически у Scala нет перегрузки операторов.
Как ни крути, перегрузка операторов не так уж плоха, даже в C ++. Проблема в том, что плохие программисты злоупотребляют этим. Но, честно говоря, я придерживаюсь мнения, что устранение способности программистов злоупотреблять перегрузкой операторов не дает оснований исправлять все то, что программисты могут злоупотреблять. Настоящий ответ - наставничество. http://james-iry.blogspot.com/2009/03/operator-overloading-ad-absurdum.html
Тем не менее, существуют различия между перегрузкой операторов C ++ и гибким именованием методов Scala, которые, IMHO, делают Scala менее уязвимым и более уязвимым.
В C ++ единственный способ получить фиксированную запись - использовать операторы. В противном случае вы должны использовать object.message (аргумент) или pointer-> messsage (аргумент) или функцию (аргумент1, аргумент2). Так что если вы хотите определенный стиль DSLish для своего кода, тогда есть необходимость использовать операторы.
В Scala вы можете получить инфиксную запись с любым отправленным сообщением. «Аргумент объекта сообщения» совершенно нормально, что означает, что вам не нужно использовать несловарные символы только для того, чтобы получить инфиксную запись.
Перегрузка операторов C ++ ограничена по существу операторами C. В сочетании с ограничением, что только операторы могут использовать инфикс, который заставляет людей пытаться отобразить широкий спектр несвязанных понятий на относительно небольшое количество символов, таких как «+» и «>>»
Scala допускает огромный диапазон допустимых несловесных символов в качестве имен методов. Например, у меня есть встроенный DSL Пролог, где вы можете написать
Символы: -,!,? И & определяются как обычные методы. В C ++ только & будет допустимым, поэтому попытка отобразить этот DSL в C ++ потребует некоторых символов, которые уже вызывают совершенно разные понятия.
Конечно, это также открывает Scala для другого вида злоупотреблений. В Scala вы можете назвать метод $! & ^%, Если хотите.
Для других языков, которые, например, Scala, являются гибкими в использовании несловесных функций и имен методов, см. Smalltalk, где, как и Scala, каждый «оператор» - это просто еще один метод, и Haskell, который позволяет программисту определять приоритет и фиксированность гибко именованных имен. функции.
источник
int main() {return (3).operator+(5);}
Результаты @Joshuaerror: request for member ‘operator+’ in ‘3’, which is of non-class type ‘int’
Только по невежеству. Это абсолютно необходимо в таких языках, как C ++, и заметно, что другие языки, которые начали с «пуристического» взгляда, добавили его, как только их разработчики выяснили, насколько это необходимо.
источник
Перегрузка операторов никогда не считалась плохой идеей в C ++ - просто злоупотребление перегрузкой операторов считалось плохой идеей. На самом деле не нужно перегружать операторы в языке, так как в любом случае их можно смоделировать с помощью более подробных вызовов функций. Избежание перегрузки операторов в Java сделало реализацию и спецификацию Java немного проще и заставило программистов не злоупотреблять операторами. В сообществе Java были споры о введении перегрузки операторов.
Преимущества и недостатки перегрузки операторов в Scala такие же, как и в C ++ - вы можете написать более естественный код, если вы правильно используете перегрузку операторов, - и более загадочный, запутанный код, если вы этого не сделаете.
К сведению: операторы не определены как специальные функции в C ++, они ведут себя так же, как и любая другая функция - хотя есть некоторые различия в поиске имен, должны ли они быть функциями-членами, и тот факт, что их можно вызывать двумя способами: 1 ) синтаксис оператора и 2) синтаксис идентификатора оператора-функции.
источник
add(2, multiply(5, 3))
?Эта статья - « Позитивное наследие C ++ и Java » - напрямую отвечает на ваш вопрос.
Java по ошибке (по мнению автора) пропустила перегрузку операторов, потому что это было сложно в C ++, но забыла почему (или не поняла, что это не относится к Java).
К счастью, языки более высокого уровня, такие как Scala, предоставляют разработчикам возможности, но при этом работают на той же JVM.
источник
В перегрузке операторов нет ничего плохого. На самом деле, что-то не так с отсутствием перегрузки операторов для числовых типов. (Взгляните на некоторый код Java, который использует BigInteger и BigDecimal.)
C ++ имеет традицию злоупотреблять этой функцией. Часто цитируемый пример - операторы сдвига битов перегружены для выполнения операций ввода-вывода.
источник
=
вместо<<
и>>
в первые дни C ++, но столкнулся с проблемами, поскольку у него не было правильного приоритета оператора (т.е. он ищет аргументы слева или справа вначале). Так что его руки были немного связаны с тем, что он мог использовать.В целом это не плохо.
Новые языки, такие как C #, также имеют перегрузку операторов.
Злоупотребление перегрузкой операторов - это плохо.
Но есть также проблемы с перегрузкой операторов, как это определено в C ++. Поскольку перегруженные операторы являются просто синтаксическим сахаром для вызовов методов, они ведут себя так же, как методы. С другой стороны, обычные встроенные операторы не ведут себя как методы. Эти несоответствия могут быть причиной проблем.
С верхней части моей головы операторов
||
и&&
.Встроенные версии этих операторов являются сокращенными. Это не относится к перегруженным версиям и вызвало некоторые проблемы.
Тот факт, что + - * / все возвращают тот же тип, с которым они работают (после повышения
статуса оператора) . Перегруженные версии могут возвращать что угодно (Вот где начинается злоупотребление, если ваши операторы начинают возвращать некоторый тип арбитра, которого пользователь не ожидал дела идут вниз по склону).
источник
Перегрузка операторов - это не то, что вам действительно «нужно» очень часто, но при использовании Java, если вы попадаете в точку, в которой вы действительно нуждаетесь, вы захотите вырвать ногти, чтобы у вас был повод прекратить печатать ,
Тот код, который вы только что нашли, давно переполнен? Да, вам придется перепечатать всю партию, чтобы она работала с BigInteger. Нет ничего более разочаровывающего, чем необходимость изобретать велосипед просто для изменения типа переменной.
источник
Гай Стил утверждал, что перегрузка операторов должна быть и в Java, в своей основной речи «Развитие языка» - есть видео и его транскрипция, и это действительно потрясающая речь. Вам будет интересно, о чем он говорит на первых двух страницах, но если вы продолжите читать, вы увидите смысл и достигнете просветления. И тот факт, что он вообще мог выступить с такой речью, тоже удивителен.
В то же время, этот доклад вдохновил многих фундаментальных исследований, возможно, в том числе Scala - это одна из тех статей, которые каждый должен прочитать, чтобы работать в этой области.
Возвращаясь к делу, его примеры в основном касаются числовых классов (например, BigInteger и некоторых странных вещей), но это не обязательно.
Правда, злоупотребление перегрузкой операторов может привести к ужасным результатам, и даже правильное использование может усложнить ситуацию, если вы попытаетесь прочитать код, не изучая немного библиотек, которые он использует. Но разве это хорошая идея? OTOH, не должны ли такие библиотеки попытаться включить шпаргалку для своих операторов?
источник
Я верю, что КАЖДЫЙ ответ пропустил это. В C ++ вы можете перегружать операторы сколько хотите, но вы не можете влиять на приоритет, с которым они оцениваются. У Scala нет этой проблемы, IIRC.
Что касается того, что это плохая идея, помимо проблем с приоритетами, люди придумывают действительно глупые значения для операторов, и это редко способствует удобочитаемости. Библиотеки Scala особенно плохи для этого, глупые символы, которые вы должны запоминать каждый раз, когда администраторы библиотек торчат головой в песке, говоря: «Вам нужно выучить это только один раз». Отлично, теперь мне нужно выучить загадочный синтаксис "умного" автора * количество библиотек, которые я хочу использовать. Это не было бы так плохо, если бы существовало соглашение ВСЕГДА, предоставляющее грамотную версию операторов.
источник
Перегрузка операторов не была изобретением C ++ - она пришла от Algol IIRC, и даже Гослинг не утверждает, что это плохая идея в целом.
источник
Единственное, что неправильно известно в C ++ - это отсутствие возможности перегрузить [] = как отдельный оператор. Это может быть трудно реализовать в компиляторе C ++, что, вероятно, не является очевидной причиной, но многое стоит того.
источник
Как указали другие ответы; перегрузка оператора сама по себе не обязательно плохая. Что плохо, когда он используется таким образом, что результирующий код неочевиден. Как правило, при их использовании вы должны заставить их делать наименьшую удивительную вещь (разделение оператор + делание может создать проблемы для рационального использования класса) или, как говорит Скотт Мейерс:
Теперь некоторые люди довели перегрузку операторов до крайности такими вещами, как boost :: spirit . На этом уровне вы понятия не имеете, как это реализовано, но он делает интересный синтаксис, чтобы получить то, что вы хотите сделать. Я не уверен, хорошо это или плохо. Вроде неплохо, но я этим не пользовался.
источник
Я никогда не видел статьи, утверждающей, что перегрузка операторов C ++ - это плохо.
Определяемые пользователем операторы обеспечивают более высокий уровень выразительности и удобства использования для пользователей языка.
источник
AFAIK, нет ничего особенного в операторских функциях по сравнению с "нормальными" функциями-членами. Конечно, у вас есть только определенный набор операторов, которые вы можете перегружать, но это не делает их особенными.
источник