Использование только std :: exception в спецификации исключений - PullRequest
2 голосов
/ 04 декабря 2008

Кажется, общепризнанно, что спецификации исключений помогают не так сильно, как думают. Но мне интересно, если спецификация, которая использует только 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 );

Ответы [ 4 ]

8 голосов
/ 04 декабря 2008

Да, но что вы ожидаете случиться, если что-то, не производное от std :: exception, выброшено?

Хотите, чтобы приложение прекратило работу?
Нет разматывания стека, не вызывается деструктор, чтобы привести в порядок код, только приложение закрывается.

Разница между спецификациями исключений Java и C ++ заключается в том, что Java проверяет спецификации во время компиляции. С ++, с другой стороны, выполняет всю проверку во время выполнения. Так что к тому времени, когда ваши спецификации были нарушены, уже слишком поздно.

Даже в коде Java есть движение, чтобы прекратить использовать их. То, что имеет место, происходит в начале проекта, спецификации исключений четко определены. Но по мере роста и усложнения кода спецификации разбавляются до все более общей формы. Это связано с тем, что по мере роста кода может возникать больше исключений, и, если они не могут быть обработаны немедленно, вам необходимо изменить спецификации исключений всей цепочки вызовов обратно к точке, где они могут быть обработаны. (Обратите внимание, я не эксперт по Java, но я играю в зрелой Java-базе кода).

Единственная спецификация исключения (я думаю), которая стоит многого, - это спецификация без бросков. Это действительно действующее приложение (но вы должны использовать его с блоком try / catch (...)).

Также читайте Статья Херба Саттерса :

И этот поток на SO: Должен ли я использовать спецификатор исключений в C ++?

4 голосов
/ 04 декабря 2008

Спецификации исключений практически бесполезны. Мартин Йорк уже ссылался на пост Херба Саттера о них, но вкратце вы столкнулись со следующими проблемами:

  1. Они игнорируются MSVC, а
  2. Их эффект не похож на Джава. Технические характеристики проверены во время выполнения, вызывая производительность ударил, дав вам проверка во время компиляции вы получаете в Джава. Все, что вы говорите: «Вставьте дополнительный код, чтобы при выдается исключение, проверяется его тип, а затем либо брось как обычно, либо позвони вместо этого неожиданный ().

Таким образом, все, что вы делаете, это усложняет отлов исключений, которые могут быть выброшены, и в то же время замедляет вашу программу. В этом нет особого смысла.

2 голосов
/ 04 декабря 2008

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

Таким образом, может быть цена, и все, что вы получаете, это то, что, если someFunction или что-то вызываемое им, поднимается для исключения, не полученного std::exception, вызывается std::unexpected, а не механизм необработанного исключения.

Так что я думаю, мой ответ «Нет»: -)

1 голос
/ 05 декабря 2008

Я бы сделал так:

void someFunction() /* throw (std::exception) */;

Единственный эффект оператора throw в объявлении функции заключается в изменении его подписи: указатель на «void x ()» и указатель на «void x () throw y» - это два разных типа.
Таким образом, вы по-прежнему документируете, что функция может что-то выбросить, и ничего не теряете, так как компилятор c ++ в любом случае не накладывает никаких ограничений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...