2013-07-31 2 views
3

Я читаю следующий текст в прикладной книге на C++.Исключение, вызванное функциями обработчика

Можно ли исключить исключения изнутри наших функций обработчика? Ответ да, ошибка действительно может быть брошена. Проблема заключается в том, что это исключение должно быть в каждой спецификации исключения, которая может быть переведена до тех пор, пока не будет обнаружено исключение. Если это не будет сделано, приложение вызовет std :: terminate(). Для большой системы это сводится к добавлению спецификации исключения к каждой функции, , если вы не понимаете динамику своего приложения. Он также важен для всех исключений в вашем деструкторе; иначе std :: terminate() также будет вызываться в этом случае.

В приведенном выше тексте у меня есть следующие вопросы и вам нужна ваша помощь в понимании.

  1. Что означает автор, «исключение должно быть в каждой спецификации истечения, которая может быть пройдена»?

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

Просьба уточнить, с простыми примерами

Спасибо за ваше время и помощь.

ответ

0
  1. Исключение спецификация оказалась плохой идея, и я думаю, что они являются устаревшими в последней версии языка, так что я бы просто игнорировать его.

  2. Вообще говоря, деструкторы не должны вызывать никаких исключений. Потому что они вызываются во время разворачивания стека, которое происходит, когда исключение выбрано/уловлено. Если при запуске стека возникает исключение, программа прерывается. Легким/безопасным решением является обертывание корпуса деструктора блоком try {...} catch (..} {}.

+1

Никогда не используйте или не рекомендует кому-либо еще иметь предложение catch-all, которое не отменяет или отменяет приложение. –

+0

@ VladLazarenko IMO, это не имеет никакого отношения к рекомендациям - это OP, спрашивающий, что автор означает цитатой, и «поймать все исключения» довольно однозначно в этом случае –

+1

@ mel-: Нет, поймать все исключения означает поймать все исключения. Хорошие разработчики на C++ никогда не будут использовать так называемую catch-all. Для примера, прочитайте [this] (http://udrepper.livejournal.com/21541.html). –

1

Если исключение выбрано и не поймано, стек раскручивается. Это означает, что будут вызваны деструкторы, все будет хорошо очищено. Но подумайте:

foo::~foo() 
{ 
    bar(); 
} 

Если мы достигнем деструктора foo из неперехваченного исключения, и bar(); происходит бросить, приложение немедленно прекращается, потому что C++ не может обрабатывать более чем одно исключение сразу.

Этого не произошло бы, если бы мы, например.проглотил исключение:

foo::~foo() 
{ 
    try { bar(); } catch(...) { /* nom nom */ } 
} 

Обновление:

Первая часть относится к спецификации исключений, как это:

struct foo 
{ 
    void bar() throw(); 
} 

Действительный синтаксис для данной спецификации

throw() // does not throw any exception 
throw(list of exceptions) // may throw one of these exceptions 
throw(...) // may throw any exception 

, но как упомянуто Rodrigo, это оказалось из-за того, что эти спецификации привели к динамическим проверкам (во время выполнения), выбрасывается ли исключение, что значительно замедляет производительность.

В C++ 11 он заменяется noexcept ключевым словом:

noexcept(true) 
noexcept(false) 
noexcept // identical to noexcept(true) 

который является гарантией того, что вы даете компилятор, а не наоборот.

Но теперь, наконец, на ваш вопрос. Когда вы даете спецификацию исключения в некоторой вложенной цепочке, и вы генерируете исключение в глубоко вложенной функции, вам придется обновить подпись каждой функции на этом пути. Еще одна очень хорошая причина, почему спецификации исключений были глупыми и больше не должны использоваться.

+0

@ nijansen: Спасибо за разъяснение. Не могли бы вы уточнить первый вопрос? – venkysmarty

+0

@venkysmarty обновил мой ответ – nijansen

2

Как правило, спецификации исключений являются плохими идеями, поскольку они вызывают много проблем рефакторинга и масштабирования (проблемы, о которых говорит автор) при изменении спецификаций. Это относится к java checked exceptions. C++ не имеет проверенных исключений, но проблема с спецификациями исключений одинакова, если вы хотите написать единый API.

Фактически exception specifications are deprecated since C++11. C++ 11 использует спецификатор noexcept, чтобы гарантировать, что функция не выбрасывает какое-либо исключение. Это позволяет определенные оптимизации компилятора и, конечно же, предоставляет гарантии для пользователя функции. Если функция не имеет спецификатора noexcept, она может генерировать исключение или нет.

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

Смежные вопросы