C++ для начинающих - страница 23
>if ( !infile ) {
>string errMsg("Невозможно открыть файл: ");
>errMsg += fileName;
>throw errMsg;
>}
Место программы, в котором исключение обрабатывается. При возбуждении исключения нормальное выполнение программы приостанавливается и управление передается обработчику исключения. Поиск нужного обработчика часто включает в себя раскрутку так называемого стека вызовов программы. После обработки исключения выполнение программы возобновляется, но не с того места, где произошло исключение, а с точки, следующей за обработчиком. Для определения обработчика исключения в С++ используется ключевое слово catch. Вот как может выглядеть обработчик для примера из предыдущего абзаца:
>catch (string exceptionMsg) {
>log_message (exceptionMsg);
>return false;
>}
Каждый catch-обработчик ассоциирован с исключениями, возникающими в блоке операторов, который непосредственно предшествует обработчику и помечен ключевым словом try. Одному try-блоку могут соответствовать несколько catch-предложений, каждое из которых относится к определенному виду исключений. Приведем пример:
>int* stats (const int *ia, int size)
>{
>int *pstats = new int [4];
>try {
>pstats[0] = sum_it (ia,size);
>pstats[1] = min_val (ia,size);
>pstats[2] = max_val (ia,size);
>}
>catch (string exceptionMsg) {
>// код обработчика
>}
>catch (const statsException statsExcp) {
>// код обработчика
>}
>pstats [3] = pstats[0] / size;
>do_something (pstats);
>return pstats;
>}
В данном примере в теле функции stats() три оператора заключены в try-блок, а четыре – нет. Из этих четырех операторов два способны возбудить исключения.
>1) int *pstats = new int [4];
Выполнение оператора new может окончиться неудачей. Стандартная библиотека С++ предусматривает возбуждение исключения bad_alloc в случае невозможности выделить нужное количество памяти. Поскольку в примере не предусмотрен обработчик исключения bad_alloc, при его возбуждении выполнение программы закончится аварийно.
>2) do_something (pstats);
Мы не знаем реализации функции do_something(). Любая инструкция этой функции, или функции, вызванной из этой функции, или функции, вызванной из функции, вызванной этой функцией, и так далее, потенциально может возбудить исключение. Если в реализации функции do_something и вызываемых из нее предусмотрен обработчик такого исключения, то выполнение stats() продолжится обычным образом. Если же такого обработчика нет, выполнение программы аварийно завершится.
Необходимо заметить, что, хотя оператор
>pstats [3] = pstats[0] / size;
может привести к делению на ноль, в стандартной библиотеке не предусмотрен такой тип исключения.
Обратимся теперь к инструкциям, объединенным в try-блок. Если в одной из вызываемых в этом блоке функций – sum_it(), min_val() или max_val() –произойдет исключение, управление будет передано на обработчик, следующий за try-блоком и перехватывающий именно это исключение. Ни инструкция, возбудившая исключение, ни следующие за ней инструкции в try-блоке выполнены не будут. Представим себе, что при вызове функции sum_it() возбуждено исключение:
throw string ("Ошибка: adump27832");
Выполнение функции sum_it() прервется, операторы, следующие в try-блоке за вызовом этой функции, также не будут выполнены, и pstats[0] не будет инициализирована. Вместо этого возбуждается исключительное состояние и исследуются два catch-обработчика. В нашем случае выполняется catch с параметром типа string:
>catch (string exceptionMsg) {
>// код обработчика
>}
После выполнения управление будет передано инструкции, следующей за последним catch-обработчиком, относящимся к данному try-блоку. В нашем случае это
>pstats [3] = pstats[0] / size;
(Конечно, обработчик сам может возбуждать исключения, в том числе – того же типа. В такой ситуации будет продолжено выполнение catch-предложений, определенных в программе, вызвавшей функцию stats().)
Вот пример:
>catch (string exceptionMsg) {
>// код обработчика
>cerr "stats(): исключение: "
> exceptionMsg
> endl;
>delete [] pstats;
>return 0;
>}
В таком случае выполнение вернется в функцию, вызвавшую stats(). Будем считать, что разработчик программы предусмотрел проверку возвращаемого функцией stats() значения и корректную реакцию на нулевое значение.