try…catch Пустой throw

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

У этой операции есть два назначения:

  • Выход из цепочки работающих обработчиков детонируемых
    throw

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

  • Cброс можно делать только в блоке обработки, т. е. только внутри catch, но не внутри try
  • Сбрасываемая обработка должна быть обёрнута своим блоком try-catch, иначе сброс приводит к попытке выпрыгивания за пределы блоков try-catch, что приводит к ошибке неперехваченного исключения (см. листинг #1.2)

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

В листинге #1.3 несколько раз возбуждаются исключительные ситуации в порядке цепной реакции, но в какой обработчик мы должны попасть? Компилятор ищет ближайший внешний (и при этом подходящий по типу), но такового нет, и происходит ошибка. Ближайший внешний от первого сработавшего throw. Можно сложить в матрёшку очень много исключений: когда после срабатывания одного throw будет детонировать ещё одно, а то детонировать своё, а то сдетонированное своё… Но сброс будет выводить нас в ближайший внешний catch от первого сдетонировавшего исключения:

Теперь рассмотрим другой случай: втаскивание исключения в обработчик. Такое достигается путём использования пустого throw внутри обработчика, т. е. внутри блока catch, но чтобы втаскивание прошло удачно, нужно, чтобы некоторое исключение было активизировано, т. е. throw_тип должно "сдетонировать". Поскольку мои слова только всё усложнят, начнём с изучения примера:

Т. е. втаскивание, это когда можно не писать в бросаемое исключение тип, и всё равно затащит в блок обработчика, т. е. в catch. Но, ещё раз повторю, должно быть активизировано исключение, которое втащило ход работы в своий catch, а внутри такого блока catch можно втащить во внутренний catch, указав пустой throw в части try.
Будьте внимательными, для сброса пустой throw указываем обязательно в обработчике (в catch), а для втаскивания в блоке try. На самом деле запомнить это несложно: достаточно уметь немного логически мыслить: втащить можно, если мы ещё не в catch, а выйти, если мы уже в catch; и в одном и в другом случае должен быть внешний try-catch_блок, но в одном случае внутренний try-catch_блок в try-части внешнего try-catch_блока, а во втором в catch-части внешнего try-catch_блока.
Посмотрим ещё один пример. Исключения сильно напоминают goto, можно прыгать и скакать, и всех запутывать, и себя запутать.

Ну как, стало лучше видно в чём различие?
Не забывайте, что чтобы можно было "втащить", нужно активизированное исключение. Так, в листинге #3.2 мы сначала активизировали исключение throw 1, после чего сработало всё цепочкой, и только потому что была та активизация, внутри функции foo_catch_container, мы удачно совершили прыжок в catch. Если не активизировать исключение, то получим ошибку времени выполнения:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Поиск

 
     

Случайная книга в электронном формате

https://www.litres.ru/andrey-borovskiy/qt4-7-prakticheskoe-programmirovanie-na-c-2/?lfrom=15589587
Яндекс.Метрика