Похоже, общепринято, что спецификации исключений не помогают так сильно, как кажется. Но мне интересно, может ли спецификация, в которой используется только std :: exception, быть хорошим компромиссом:
void someFunction()
throw ( std::exception );
Он документирует тот факт, что этот метод / функция может вызвать исключение.
Это гарантирует, что генерируются только исключения, производные от std :: exception, а не некоторые экзотические классы, такие как std :: string или int.
Так что лучше, чем вообще не иметь спецификации?
Обновлять:
Что касается накладных расходов во время выполнения: подумайте об этом как об использовании утверждений. Вы используете утверждения независимо от накладных расходов времени выполнения, верно? Я знаю, что вы обычно можете отключить их для сборки выпуска, поэтому, возможно, лучше было бы обернуть спецификацию исключения в макрос, чтобы вы могли отключить его для сборки выпуска. Что-то типа:
#ifdef DEBUG
#define THROW( exception ) throw ( exception )
#else
#define THROW( exception )
#endif
void someFunction()
THROW( std::exception );





В соответствующем компиляторе добавление непустой спецификации исключения генерирует эквивалент блока try / catch вокруг функции. Хотя это можно реализовать без дополнительных затрат времени выполнения, в некоторых текущих компиляторах накладные расходы действительно возникают.
Таким образом, это может быть связано с затратами, и все, что вы получаете, это то, что если someFunction или что-то, что он вызывает, вызывает исключение, не производное от std::exception, вызывается std::unexpected, а не механизм необработанных исключений.
Думаю, мой ответ - «Нет» :-)
Добавление блока try / catch практически не требует затрат (при отсутствии распространения исключений) в современных компиляторах, так что это вызывает беспокойство.
Я изменю свою формулировку - «самые современные компиляторы» были неправильными. Но если вы компилируете для 32-разрядной версии с помощью Visual Studio, это все равно нужно учитывать.
Хм, я только что заметил другой ответ, в котором говорится, что VC++ полностью игнорирует спецификацию исключений, и я думаю, что это может быть правильно. Ну да ладно ... это все еще плохая идея :-)
На самом деле MSVC уважает метод nothrow (или, скорее, использует его как подсказку по оптимизации), но игнорирует все другие спецификации и никогда не вызывает std :: неожиданный.
Да, но что вы ожидаете, когда возникает что-то, что не является производным от std :: exception?
Вы хотите, чтобы приложение было закрыто. Никакой раскрутки стека и вызова деструкторов для очистки кода, только завершение работы приложения.
Разница между спецификациями исключений Java и C++ заключается в том, что Java проверяет спецификации во время компиляции. C++, с другой стороны, выполняет все проверки во время выполнения. Так что к тому времени, когда ваши требования будут нарушены, будет уже слишком поздно.
Даже в коде Java есть движение, чтобы перестать их использовать. Что обычно происходит в начале проекта, спецификации исключений четко определены. Но по мере того, как код растет и становится более сложным, спецификации размываются до все более и более общей формы. Это связано с тем, что по мере роста кода может возникать больше исключений, и если они не могут быть обработаны немедленно, вам необходимо изменить спецификации исключений для всей цепочки вызовов до точки, в которой они могут быть обработаны. (Обратите внимание, что я не эксперт по Java, но я играю на зрелой базе кода Java).
Единственная спецификация исключения (я думаю), которая имеет большое значение, - это спецификация запрета на выброс. У этого есть действующее приложение (но вы должны использовать его с блоком try / catch (...)).
Также прочтите Статья Херба Саттерса:
И эта ветка на SO: Следует ли использовать спецификатор исключения в C++?
Хорошее объяснение проблем со спецификациями, проверенными во время компиляции. Я обсуждал это несколько раз за эти годы ...
@Martin York: обратите внимание, что совет Херба Саттера - НЕ использовать даже пустую спецификацию исключения. См. gotw.ca/publications/mill22.htm
Спецификации исключений по сути бесполезны. Мартин Йорк уже ссылался на пост Херба Саттера о них, но вкратце вы сталкиваетесь со следующими проблемами:
Таким образом, все, что вы делаете, - это усложняете перехват исключения, которые могут возникнуть, и в то же время замедляете работу вашей программы. В этом нет особого смысла.
Мир не вращается вокруг MSVC ;-), и я не понимаю, как было бы сложнее поймать выброшенное исключение, поскольку единственное, что он предотвращает, - это генерировать какое-то произвольное исключение, а не исключение на основе std :: exception.
ПРОЧИТАЙТЕ сообщение Саттерса! Они НЕ предотвращают создание произвольных исключений. Они только предотвращают НАХОЖДЕНИЕ произвольных исключений - главное отличие.
Я прочитал сообщение. Я могу согласиться с тем, что, строго говоря, они НЕ ПРЕДОТВРАЩАЮТ произвольных исключений. Но поскольку программа будет прервана (если вы создадите другое исключение и не настроили обработчик ошибок с помощью set_unexpected), она очень похожа на assert.
Я бы сделал это типично:
void someFunction() /* throw (std::exception) */;
Единственный эффект оператора throw в объявлении функции - изменить ее сигнатуру: указатель на «void x ()» и указатель на «void x () throw y» - это два разных типа. Таким образом, вы все еще документируете, что функция может что-то выбросить, и вы ничего не теряете, поскольку компилятор C++ в любом случае не применяет никаких ограничений.
Нет, это ни в чем не гарантирует. Это проблема. Вы обещаете, что больше ничего не будет брошено, вы не просите компилятор проверить, что это действительно так.