Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > C/C++: Общие вопросы > Оператор , |
Автор: vinter 6.6.2008, 14:46 | ||
привет всем, сегодня увидел такой код
ни разу не задумовался о запятых, и решил что этот код неверен, я ошибся. Теперь внимание вопрос, нафига это сделано? и второй вопрос зачем тогда нужны ; , если почти все заменяют запятые в том числе и тело цикла? |
Автор: Любитель 6.6.2008, 16:05 |
Запятые нужны в си, в первую очередь для форов (ну, не то, чтоб нужны - но удобно). В С++ - это, во-первых, наследие. Но кроме того есть перегрузка операторов, потому находятся и другие применения. Например, boost::asign. |
Автор: JackYF 7.6.2008, 00:33 |
Запятые также иногда удобны в условиях конструкций if и while. |
Автор: chipset 7.6.2008, 21:24 |
А ещё запятые можно перегружать ![]() |
Автор: bronislav 8.6.2008, 21:30 |
Специально для этого их и придумали ![]() |
Автор: Alek86 9.6.2008, 09:40 |
можно пример, когда они удобны? ато я так сразу представить не могу |
Автор: Fazil6 9.6.2008, 10:57 |
совсем не для этого. Семантика оператора "," меняется при перегрузке и поэтому не рекомендуется его перегружать. Тудаже относится и перегрузка && и || |
Автор: Lazin 9.6.2008, 11:21 |
да вроде-бы можно перегружать, но только для своих классов... |
Автор: Fazil6 9.6.2008, 11:51 | ||
перегружать можно, но поведение его будет очень сильно отличаться. Реализовать его семантику при перегрузке невозможно, поэтому результат этого перегруженного оператора будет очень удивительным для пользователя класса. Вы ведь не будете перегружать "+" так чтобы он в итоге реализовывал "-"... Добавлено через 9 минут и 15 секунд вот подобный случай обсуждался
|
Автор: Любитель 9.6.2008, 12:42 |
Fazil6, семантику менять - это нормально. Иногда Пример я уже привёл (boost::assign). |
Автор: JackYF 9.6.2008, 17:18 | ||
|
Автор: MAKCim 9.6.2008, 17:39 |
почему? |
Автор: Alek86 9.6.2008, 18:01 |
JackYF, конечно спорно ради одной строчки так (имхо) загрязнять читаемость наверное, к этом нужно привыкнуть.......... |
Автор: Fazil6 9.6.2008, 18:01 |
потому, что нужно обеспечить порядок вычисления операндов |
Автор: MAKCim 9.6.2008, 18:20 |
и в чем проблема? приведи пример, что по-твоему невозможно сделать |
Автор: d06osipov 9.6.2008, 19:09 | ||
Во-первых, я что-то не слышал про стандартную семантику && и ||. А во-вторых, при перегрузке копирующего конструктора и оператора = тоже меняется семантика. Это значит, их не рекомендуется перегружать? |
Автор: Fazil6 9.6.2008, 20:26 | ||||
не совсем понимаю вопроса. В свою очередь встречный вопрос: как обеспечить чтобы левый операнд вычислялся всегда первым, а правый вторым?
ну и чем ты гордишься? Почитай топик по ссылке - там четко видно к чему приводит перегрузка ||
в четырнадцатых слабо себе представляю перегрузку копирующего конструктора, с изменяющейся семантикой... Понимаешь, старик, можно прегрузить к примеру operator-, изменив его семантику так, чтобы он делал умножение (согласись, это оригинально, ведь именно для этого перегрузку придумали). После этого в лучшем случае ты будешь проклят своими колегами, а может и покалечат (оторвут руки) |
Автор: andrew_121 9.6.2008, 20:58 | ||
Интересная дискуссия. Много нового узнал... Но правда, не вижу надобности перегружать "operator ,". |
Автор: bsa 9.6.2008, 21:14 | ||||
andrew_121, действительно, надобности это делать почти никогда нет. Но, иногда встречаются случаи, когда сделав это мы получим что-то, например, удобочитаемость кода. Пример, что лучше выглядит, это:
|
Автор: andrew_121 9.6.2008, 21:20 |
bsa: Да, беспорно, красивей, удобней, понятней! Респект! Слышал про Boost, но некогда не юзал, поделитесь ссылками на оного. И на доки, и на форум об оном тожА. Плиз. |
Автор: bsa 9.6.2008, 21:38 | ||||
http://www.google.com/search?q=boost Добавлено через 2 минуты и 6 секунд
Вся хитрость операторов && и || в том, что они не вычисляют второй свой аргумент, если уже по первому известен результат. |
Автор: skyboy 9.6.2008, 21:51 |
почитайте про http://alenacpp.blogspot.com/2005/11/sequence-points.html undefined behavior не страшен только тем, кто "намертво" прикреплен к одной версии определенного компилятора. В противном случае, может оказаться, что программа работает не так, как надо. Только потому, что кто-то ради "удобочитаемости"(и то - спорно) вместо пяти точек следования(к примеру; т.е. 5 строк с ";" в конце) сделал одну(после выражения перед первой запятой в строке). |
Автор: andrew_121 9.6.2008, 22:43 |
skyboy: То же вариант. |
Автор: d06osipov 10.6.2008, 09:03 | ||||
А что, есть смысл перегружать что-либо без изменения семантики?
Перегрузка && и ||, как и перегрузка любых других операторов, приводит к изменению их семантики (вполне возможно, предыдущая семантика --- ошибка компиляци). Есть одна стандартная версия &&, || и т. п. для параметров (bool,bool) которую можно применять к указателям используя конвертацию указателей к bool. Что же может испортить перегрузка этих операторов для объектов и ссылок на объекты? Даже для указателей, мне кажется, гораздо опаснее использовать неявную конвертацию к bool, чем перегружать для них оператор && (тем более, что для (bool,bool) его нельзя перегрузить). |
Автор: Fazil6 10.6.2008, 09:58 | ||||
конечно. Именно так и нужно перегружать. Что по твоему семантика? Семантика оператора - это его смысл. Смысл оператора "+" в сложении. Вот и перегружать его надо так, чтобы он по смыслу делал сложение. Где тут изменение семантики?
это поведение не ошибка, а соответствие стандарту. |
Автор: d06osipov 10.6.2008, 10:08 | ||
Я имел ввиду вот что:
В этом случае --- семантика оператора a1||a2 --- ошибка компиляции. Мы с вами по разному понимаем слово семантика. Я вкладываю в него не смысл, а то, что конкретно делает данная сущность (строгое определение во всех деталях), иными словами --- описание изменения состояния машины после выполнение данной сущности. А смысл я называю спецификацией (пример: +. Спецификация: сложить два числа. Семантика: записывает в стек сумму двух чисел без побочных эффектов). В этом случае, перегружать, не меняя семантики --- значит, писать тавтологичный код. |
Автор: Fazil6 10.6.2008, 10:17 | ||
Не понимаю. В чем тогда по-твоему изменение семантики при перегрузке "+" для каких-нибудь объектов учитывая, что спецификация не изменилась(сложить два объекта)? |
Автор: Alek86 10.6.2008, 10:36 | ||
значит для тебя перегрузка оператора не должна менять его спецификацию а для оператора "," это не возможно |
Автор: vinter 10.6.2008, 11:17 | ||
как это будет работать? т.е сначала выполняется std::getline(std::cin, s), потом !std::cin.eof(), а что проверяется в while? возвращаемое значение std::getline(std::cin, s)? |
Автор: Fazil6 10.6.2008, 11:43 |
последнее, т.е. !std::cin.eof() |
Автор: Любитель 10.6.2008, 12:22 | ||
В большинстве случаев это верно. Но иногда удобна перегрузка без следования этим правилам. boost::asign, boost::lambda, boost::optiona, etc. - в качестве примеров. |
Автор: andrew_121 10.6.2008, 12:45 |
Это дискуссия, безконечна... Спорить не буду, за - то же. Как не крути, но в перегрузке "oprator ," больше негатива, чем позитива. Так же, перегрузка "||" и "&&" вносит больше подозрений, непонятки, в код ее использующий. Зачем забивать себе голову еще и тем что, нужно помнить что эти операторы перегружены, когда и так у программера в голове, полно всякой полезной, и безполезной информации. Ведь проще написать пару лишних строк, чем забивать себе голову...(имхо) |
Автор: JackYF 10.6.2008, 15:04 |
оператор "запятая" возвращает значение последнего аргумента ![]() |
Автор: Lazin 10.6.2008, 15:18 |
неперегруженый, а перегруженый, может вернуть что угодно ![]() |
Автор: d06osipov 10.6.2008, 15:49 | ||||
Согласен. Но в большинстве случаев, программист знает, на что он идёт. И, скажем, если вы разрабатываете библиотеку, перегрузка оператора "," может испортить программу при подключении только в том случае, если: 1. Этот оператор объявлен все namespace, или используется using namespace (в противном случае, при уже существующей встроенной реализации "," будет выбираться пользовательская только в том случае, когда один из операндов имеет тип, находящийся в этом namespace, что не навредит. См. разрешение имён) 2. Этот оператор объявлен для типов, существующих вне библиотеки, например: template<class T,class S> T& operator , (const T&,const S&); //так делать не надо В Boost этот оператор применяется при левом аргументе имеющем совершенно скрытый тип, о котором пользователь даже не знает. Следовательно, этот оператор не может помешать правильной работе программы. Оператор "," полезно использовать вместо эллипса! Но надо быть осторожнsм, чтобы компилятор не воспринял , за знак отделения аргументов функции:
Т. о. Перегружать оператор , следует только в том случае, когда тип одного из операндов --- класс, к которому больше никак обращаться не следует. |
Автор: Alek86 10.6.2008, 16:11 | ||
помойму это совсем не обязательно, ведь сначала компилер "примеряет" юзерские переопределения, а только потом подставяляет стандартные |
Автор: Любитель 10.6.2008, 16:40 |
Нет, как раз в данном случае сработает вызов функции с двумя параметрами. Поэтому использование запятой как подмены функции с произвольным количеством параметров - не лучшее решение ![]() |
Автор: d06osipov 10.6.2008, 16:53 | ||
Запятая при вызове функции это не переопределение, а синтаксическая конструкция. На тех компиляторах, на которых я пробовал, это воспринималось как разделение аргументов. Не знаю, оговорено ли это явно в Стандарте, или нет, но в любом случае, лучше при использовании запятых заключить аргумент в скобки (как в примере). |
Автор: Fazil6 11.6.2008, 09:28 |
оговорено. в аргументах без скобок запятая не оператор |
Автор: vinter 11.6.2008, 10:02 |
ммм, всем спасибо за ответы. Спор помоему пошел ни о чем. Подведу итог: использование запятой ухудшает читабельность кода, но в некоторых случаех запятая удобна(перегруженная) как в случае с boost. Всем спасибо за ответы. |