Это — только плохой дизайн и не более того.
Если класс Х предполагается использовать даже в том случае, если он не смог инициализироваться (что слегка абсурдно, но в реальных задачах и не такое встречается) — например, использовать какое-то дефолтное значение, то класс и должен быть спроектирован именно так.
Вы приводите примеры из трех строчек, оторванные от жизни.
Приведите реальный пример такой пары классов, какую Вы описали, и тогда можно будт говорить предметно.
Здравствуйте jazzer, Вы писали:
J>Это — только плохой дизайн и не более того.
Ну вот, опять уперлись в "правильное проектирование". Может ты мне тогда поверишь, что можно так "правильно спроектировать", что никакой нужды в исключениях (и, тем более в конструкторах), просто не будет?
[...] J>Приведите реальный пример такой пары классов, какую Вы описали, и тогда можно будт говорить предметно.
Реальные примеры уже приводились. Никакой очевидной пользы от эксепшинов, кроме варианта с "кучей вызовов и одним местом вываливания" при ошибке хотя бы одного из вызовов я не увидел. Для таких случаев я тоже использую механизм исключений (это было описано в моей первой мессаге).
Как все запущенно...
Re[23]: Я не вижу проблем с исключениями в конструкторах (-)
От:
Аноним
Дата:
17.09.02 12:22
Оценка:
Здравствуйте Vladik, Вы писали:
V>Здравствуйте jazzer, Вы писали:
V>
DG>Где ?? оператор, который в случае исключение вызывает следующую функцию, иначе возращает значение
Кстати как вариант, ввести некоторые синтаксические конструкции для нормальной работы с исключениями, помимо уродских try/catch. Тогда все не так печально будет...
Как все запущенно...
Re[24]: Я не вижу проблем с исключениями в конструкторах (-)
Погодите, new(nothrow) означает, что оператор new не выбросит своего исключения, это не означает, что при такой записи не будет пропущено исключение, выброшенное конструктором Х.
Потому что правильное проектирование в первую очередь означает применение соответствующих средств языка в подходящих для этого ситуациях.
Если я правильно понимаю, Вы говорите: "Обычно эксепшены используются по-дурацки, и такой код выглядит маразматичным" (пример с SomeValue — лучшее тому доказательство).
Я с Вами соглашусь: если средство используется не в тех условиях, для которых оно предназначено, то код выглядит либо извращением, либо глупостью.
Только это не свойство исключений, это свойство любых средств: наследования, виртуальных функций, шаблонов и т.п.
Здравствуйте jazzer, Вы писали:
J>Потому что правильное проектирование в первую очередь означает применение соответствующих средств языка в подходящих для этого ситуациях.
J>Если я правильно понимаю, Вы говорите: "Обычно эксепшены используются по-дурацки, и такой код выглядит маразматичным" (пример с SomeValue — лучшее тому доказательство).
Я, например, хочу сказать, не то что исключения — плохо, а то что они не доведены до конца.
Как уже было выше показано, для получения информации об ошибке
1. В части случаев удобно возвращаемое значение
2. В части случаев удобно исключение
C++ позволяет легко перейти от возвращаемого значение к исключению, но обратный переход выливается в безобразного монстра — вот именно это мне и не нравится.
Здравствуйте DarkGray, Вы писали:
DG> DG>Я, например, хочу сказать, не то что исключения — плохо, а то что они не доведены до конца.
DG>Как уже было выше показано, для получения информации об ошибке DG>1. В части случаев удобно возвращаемое значение DG>2. В части случаев удобно исключение
DG>C++ позволяет легко перейти от возвращаемого значение к исключению, но обратный переход выливается в безобразного монстра — вот именно это мне и не нравится.
Мне мое использование исключений очень нравится :), но оно у меня происходило именно по первому сценарию:
я использовал разные библиотеки, основанные на кодах возврата и оборачивал их в исключения так, как мне представлялось логичным для моей задачи.
По сути (не знаю, кто еще разделит мою точку зрения), исключения являются частью public-интерфейса библиотеки/модуля, и эти исключения должны быть проработаны так же тщательно, как и интерфейс вызовов, и определяться, какие исключения данная библиотека будет выбрасывать, необходимо также на этапе проектирования.
Соответственно, хорошему разработчику неплохо бы не пренебрегать, например, возможностью объявлять функции, одновременно объявляя, какие исключения они могут выкинуть.
Здравствуйте jazzer, Вы писали:
J>Соответственно, хорошему разработчику неплохо бы не пренебрегать, например, возможностью объявлять функции, одновременно объявляя, какие исключения они могут выкинуть.
Вот! Наконец-то дошли до сути проблемы.
Ведь основные неудобства и сложности использования (реагирования на) исключения как раз в том, что в функциях (методах) нет указаний какие исключения они могут выбрасывать. А раз не указано, то получается, что могут быть выброшены любые исключения и предусматривать их обработку действительно очень муторно. Аналогичная проблема существует и с const. (автору топика) не желаешь ли и спецификатор const раскритиковать ровно с тех же позиций?
Напиример (все упрощенно, только чтобы донести суть), в "старой" библиотеке есть функция:
void writeLogС(char* msg);
Если же мы пишем обертку на С++, то очевидно наша функция будет выглядеть так:
void writeLogСPP(const char* msg);
Теперь вопрос, как должна быть реализована эта функция в терминах предыдущей.
Так?
{
writeLogC(const_cast<char*>(msg));
}
Или как-то так так (без обработки ошибок и учета исключений)?
{
char *tmp_buf = new char[strlen(msg)+1];
strcpy(tmp_buf,msg);
writeLogC(tmp_buf);
}
Ясно, что второй вариант надежнее, но сколько в итоге будет непроизводительных затрат? Вот и пишем первый вариант в надежде на здравый смысл разработчика writeLogC и на истиность его (документации) заререний о том, что его функция по указателю ничего не пишет.
С исключениями совершенно аналогично. Мы используем функции без спецификации их исключений и надеемся на то, что эти функции будут вести себя так, как если бы эта спецификация была указана. Как только же мы перестаем верить честному слову разработчиков функции (пытаемся написать действительно надежную программу), мы вынуждены писать слишком много try-catch, так как формально функция _может_ выкинуть любое исключение. Вот в этом то и состоит суть проблемы с использованием исключений в C++, IMNSHO.
Здравствуйте WeCom, Вы писали:
WC>Вот! Наконец-то дошли до сути проблемы. WC>Ведь основные неудобства и сложности использования (реагирования на) исключения как раз в том, что в функциях (методах) нет указаний какие исключения они могут выбрасывать.
Об этой проблеме я тоже упоминал в одном из "пунктов".
WC>А раз не указано, то получается, что могут быть выброшены любые исключения и предусматривать их обработку действительно очень муторно. Аналогичная проблема существует и с const. (автору топика) не желаешь ли и спецификатор const раскритиковать ровно с тех же позиций?
Я чего-то не уловил связи... В смысле критиковать отсутствие const там где он должен быть, конечно, нужно (неужели кто-то будет спорить?). Кстати, с каких пор в сях отменили const?
WC>Напиример (все упрощенно, только чтобы донести суть), в "старой" библиотеке есть функция: WC>
WC>void writeLogС(char* msg);
WC>
WC>Если же мы пишем обертку на С++, то очевидно наша функция будет выглядеть так: WC>
WC>void writeLogСPP(const char* msg);
WC>
Уж и не знаю насколько очевидно, кто-то предпочтет:
Здравствуйте WeCom, Вы писали:
WC>Здравствуйте jazzer, Вы писали:
J>>Соответственно, хорошему разработчику неплохо бы не пренебрегать, например, возможностью объявлять функции, одновременно объявляя, какие исключения они могут выкинуть.
WC>Вот! Наконец-то дошли до сути проблемы. WC>Ведь основные неудобства и сложности использования (реагирования на) исключения как раз в том, что в функциях (методах) нет указаний какие исключения они могут выбрасывать.
Эээ батенька. Посмотрите-ка пункт 15.4 стандарта.
Конечно не все компиляторы это дело поддерживают, но все равно это не дает оснований для столь категоричных заявлений.
Здравствуйте Bell, Вы писали:
WC>>Вот! Наконец-то дошли до сути проблемы. WC>>Ведь основные неудобства и сложности использования (реагирования на) исключения как раз в том, что в функциях (методах) нет указаний какие исключения они могут выбрасывать. B>Эээ батенька. Посмотрите-ка пункт 15.4 стандарта.
Расскажи это, например, борланду. Ни одного throw в объявлении функций я там не заметил.
Здравствуйте Bell, Вы писали:
B>Эээ батенька. Посмотрите-ка пункт 15.4 стандарта.
B>Конечно не все компиляторы это дело поддерживают, но все равно это не дает оснований для столь категоричных заявлений.
Я наверное недостаточно точно выразил свою мысль. Стандарт (и компиляторы) дают возможность указывать возможные исключения. Это я прекрасно знаю. НО, в РЕАЛЬНОСТИ (это важно и это я имел в виду) очень и очень мало кто этим пользуется в полной мере, отсюда и проблемы. Точно такие же как и с квалификатором const.
Здравствуйте Vladik, Вы писали:
V>Здравствуйте Bell, Вы писали:
WC>>>Вот! Наконец-то дошли до сути проблемы. WC>>>Ведь основные неудобства и сложности использования (реагирования на) исключения как раз в том, что в функциях (методах) нет указаний какие исключения они могут выбрасывать. B>>Эээ батенька. Посмотрите-ка пункт 15.4 стандарта.
V>Расскажи это, например, борланду. Ни одного throw в объявлении функций я там не заметил.
Я ведь сказал, что не все компиляторы соответствуют данному требованию стандарта
Если на то пошло, то MSVC6 тоже это не поддерживает
Здравствуйте Bell, Вы писали:
V>>Расскажи это, например, борланду. Ни одного throw в объявлении функций я там не заметил. B>Я ведь сказал, что не все компиляторы соответствуют данному требованию стандарта
Да, но даже если компилятор поддерживает это, он не обязует разработчика соответствующим образом объявлять функции.
B>Если на то пошло, то MSVC6 тоже это не поддерживает
В смысле не поддерживает??? А я вовсю использовал такую декларацию Да и в MSDN'е тоже встречаются правильные прототипы.
Здравствуйте Vladik, Вы писали:
V>Здравствуйте Bell, Вы писали:
V>>>Расскажи это, например, борланду. Ни одного throw в объявлении функций я там не заметил. B>>Я ведь сказал, что не все компиляторы соответствуют данному требованию стандарта
V>Да, но даже если компилятор поддерживает это, он не обязует разработчика соответствующим образом объявлять функции.
B>>Если на то пошло, то MSVC6 тоже это не поддерживает
V>В смысле не поддерживает??? А я вовсю использовал такую декларацию Да и в MSDN'е тоже встречаются правильные прототипы.
Поддерживает — означает, что если из функции, для которой специфицирован тип исключений, вылезло исключение неподходящего типа, то вызывается функция unexpected(). MSVC этого не делает, о чем и сообщается в документации, и при компиляции. Compiler Warning (level 3) C4290 : "C++ Exception Specification ignored".
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте Vladik, Вы писали:
V>Да, но даже если компилятор поддерживает это, он не обязует разработчика соответствующим образом объявлять функции.
Да, С++ часто не обязывает разработчика делать что-либо.
B>>Если на то пошло, то MSVC6 тоже это не поддерживает
V>В смысле не поддерживает??? А я вовсю использовал такую декларацию Да и в MSDN'е тоже встречаются правильные прототипы.
Ну вот прям в этом смысле и не поддерживает:
Note Microsoft C++ does not support exception-specifications, as described in section 15.4 of the ANSI C++ draft. In addition, it does not support function-try-block described in section 15 of the ANSI C++ draft.
Здравствуйте Bell, Вы писали:
V>>Да, но даже если компилятор поддерживает это, он не обязует разработчика соответствующим образом объявлять функции. B>Да, С++ часто не обязывает разработчика делать что-либо.
ИМХО это не тот случай, когда это хоть чем-то оправдано. С одной стороны ввели специальное объявление для функций, кидающих эксепшины, с другой — оставили это полностью на совесть разработчику. С const ситуация все же несколько иная, — да, тоже можно все испортить, но компилятор хотя бы попытается предупредить. С эксепшинами, конечно, это сделать компилятору намного сложнее (это тоже обсуждали в другом топике), точнее даже невозможно при существующем положении дел. Но хотя бы с некоторыми ограничениями было бы желательно...
Здравствуйте Vladik, Вы писали:
V>Здравствуйте Bell, Вы писали:
V>>>Да, но даже если компилятор поддерживает это, он не обязует разработчика соответствующим образом объявлять функции. B>>Да, С++ часто не обязывает разработчика делать что-либо.
V>ИМХО это не тот случай, когда это хоть чем-то оправдано. С одной стороны ввели специальное объявление для функций, кидающих эксепшины, с другой — оставили это полностью на совесть разработчику. С const ситуация все же несколько иная, — да, тоже можно все испортить, но компилятор хотя бы попытается предупредить. С эксепшинами, конечно, это сделать компилятору намного сложнее (это тоже обсуждали в другом топике), точнее даже невозможно при существующем положении дел. Но хотя бы с некоторыми ограничениями было бы желательно... :(
Все совершенно правильно сделали. Точно так же, как и с const.
Ты можешь в своих программах вообще забить на const и передавать все про неконстантным ссылкам и объектам, а для контроля того, что функция, которой ты передал неконстантную ссылку, объект не изменила, использовать контрольную сумму. После чего останется написать код с такими вызовами, после каждого вызова вставить проверки контрольной суммы и показывать всем как образец маразматичного кода :)
Та же ситуация и с исключениями.
Я, например, не очень понимаю, почему в STL (в Стандарте!) функции, по сути своей не выбрасывающие исключений (типа size()), не объявлены явно с throw(), в то время как, по-моему, версия STL от RogueWave эти спецификации имеет (и они отключаются соответствующим дефайном, если компилятор не поддерживает синтаксис).
В общем, давайте возьмемся за руки и все вместе пообещаем друг другу писать у своих функций exception specifications! (Хотя бы при помощи дефайнов :) )
Здравствуйте jazzer, Вы писали:
J>В общем, давайте возьмемся за руки и все вместе пообещаем друг другу писать у своих функций exception specifications! (Хотя бы при помощи дефайнов )
Это, конечно, замечательно. А если все на шаблонах сидит?
template <class T>
int f() // вот что здесь прописать???
{
return T::f(); // неизвестно, какие исключения f может кидать.
// мы должны пропустить их все или часть
}
Так что, в бесшаблонном коде спецификация исключений — благо, а в шаблонном — неясно, что делать.