Скачиваний:
199
Добавлен:
05.07.2021
Размер:
16.53 Mб
Скачать

14. Непредвиденное исключение. Использование функций unexpected() и set_unexpected(). Исключение типа std::bad_exception.

Если исключение не соответствует спецификации, то оно называется непредвиденным исключением и по умолчанию приводит к остановке программы.

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

double Argh(double, double) throw(out_of_bounds);

Тогда функцию можно использовать следующим образом:

try { х = Argh(а,Ь);

} catch(out_of_bounds & ex) {

//...

}

Спецификация исключений должна содержать исключения, генерируемые функциями, которые вызываются рассматриваемой функцией.

При возникновении непредвиденного исключения программа вызывает функцию unexpected(). Эта функция, в свою очередь, обращается к функции terminate(), которая по умолчанию вызывает abort(). По аналогии с функцией set_terminate(), изменяющей поведение terminate(), имеется и функция set_unexpected(), которая модифицирует поведение unexpected(). Эти новые функции также объявлены в

Однако поведение функции, которая указывается в set_unexpected(), более управляемо. В частности, функция unexpected_handler может:

  • завершить программу, вызвав terminate() (по умолчанию), abort() или

exit();

  • сгенерировать исключение.

Результат генерации исключения (второй вариант) зависит от исключения, сгенерированного функцией замены unexpected_handler, и исходной спецификации исключений для функции, которая сгенерировала непредвиденный тип исключения.

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

Если вновь сгенерированное исключение не соответствует исходной спецификации исключений и если спецификация исключений не содержит тип std::bad_exception, то программа вызывает terminate().

Если вновь сгенерированное исключение не соответствует исходной спецификации исключений и если спецификация исключений содержит тип std::bad_exception, то непредвиденное исключение заменяется исключением типа std::bad_exception.

В общем, если необходимо перехватывать все исключения — ожидаемые и непредвиденные — можно поступить примерно так. Первым делом, нужно сделать доступными объявления заголовочного файла исключений:

#include <exception> using namespace std;

Затем следует создать функцию замены, которая преобразует непредвиденные исключения в тип bad_exception с соответствующим прототипом:

void myUnexpected(){ throw std::bad_exception();//или просто throw;

}

Применение throw без указания исключения приведет к повторной генерации первоначального исключения. Но если спецификация исключений содержит этот тип, исключение будет заменено объектом bad_exception.

Далее в начале программы нужно указать функцию в качестве выбранного действия в ответ на непредвиденное исключение:

set_unexpected(myUnexpeced);

И, наконец, необходимо включить тип bad_exception в спецификацию исключений и цепочку блоков catch:

double Argh(double, double) throw(out_of_bounds, bad_exception); //...

try { x = Argh(a, b);

}

catch (out_of_bounds & ex){

}

catch(bad_exception & ex){

}