Главная » Статьи » Мои статьи » С++ для начинающих |
С++ предоставляет стандартный способ реакции на исключения.
Благодаря вынесению в отдельную часть программы кода, ответственного за
проверку и обработку ошибок, значительно облегчается восприятие текста
программы и сокращается ее размер. Единый синтаксис и стиль обработки
исключений можно, тем не менее, приспособить к самым разнообразным нуждам и
запросам. Механизм исключений делится на две основные части: точка программы, в которой произошло исключение. Определение
того факта, что при выполнении возникла какая-либо ошибка, влечет за собой возбуждение исключения. Для этого в С++
предусмотрен специальный оператор throw.
Возбуждение исключения в случае невозможности открыть некоторый файл выглядит
следующим образом:
} Место программы, в котором исключение обрабатывается. При возбуждении исключения нормальное выполнение
программы приостанавливается и управление передается обработчику исключения. Поиск нужного
обработчика часто включает в себя раскрутку так называемого стека вызовов программы. После обработки
исключения выполнение программы возобновляется, но не с того места, где
произошло исключение, а с точки, следующей за обработчиком. Для определения
обработчика исключения в С++ используется ключевое слово catch.
Вот как может выглядеть обработчик для примера из предыдущего абзаца: catch (string exceptionMsg) { log_message (exceptionMsg); return false; } Каждый catch-обработчик ассоциирован с
исключениями, возникающими в блоке операторов, который непосредственно
предшествует обработчику и помечен ключевым словом try. Одному try-блоку
могут соответствовать несколько catch-предложений,
каждое из которых относится к определенному виду исключений. Приведем пример:
{ 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-обработчиком, относящимся к данному try-блоку.
В нашем случае это pstats [3] = pstats[0] / size; (Конечно, обработчик сам может возбуждать исключения, в том числе – того же типа. В такой ситуации будет продолжено выполнение catch-предложений, определенных в программе, вызвавшей функцию stats().) Вот пример:
// код обработчика cerr << "stats(): исключение:
" << exceptionMsg << endl; delete [] pstats; return 0; } В таком случае выполнение вернется в функцию, вызвавшую stats().
Будем считать, что разработчик программы предусмотрел проверку возвращаемого
функцией stats()
значения и корректную реакцию на нулевое значение. Функция stats() умеет реагировать на два типа
исключений: string
и statsException.
Исключение любого другого типа игнорируется, и управление передается в
вызвавшую функцию, а если и в ней не найдется обработчика, – то в функцию
более высокого уровня, и так до функции main().При
отсутствии обработчика и там, программа аварийно завершится. Возможно задание специального обработчика, который реагирует
на любой тип исключения. Синтаксис его таков:
} (Детально обработка исключительных ситуаций рассматривается
в главах 11 и 19.) Упражнение 2.18 Какие ошибочные ситуации могут возникнуть во время
выполнения следующей функции: int *alloc_and_init (string file_name) { ifstream infile (file_name) int elem_cnt; infile >> elem_cnt; int *pi = allocate_array(elem_cnt); int elem; int index=0; while (cin >> elem) pi[index++] = elem; sort_array(pi,elem_cnt); register_data(pi); return pi; } Упражнение 2.19 В предыдущем примере вызываемые функции allocate_array(),
sort_array()
и register_data()
могут возбуждать исключения типов noMem, int
и string
соответственно. Перепишите функцию alloc_and_init(),
вставив соответствующие блоки try
и catch
для обработки этих исключений. Пусть обработчики просто выводят в cerr
сообщение об ошибке. Упражнение 2.20 Усовершенствуйте функцию alloc_and_init()
так, чтобы она сама возбуждала исключение в случае возникновения всех возможных
ошибок (это могут быть исключения, относящиеся к вызываемым функциям allocate_array(),
sort_array()
и register_data()
и какими-то еще операторами внутри функции alloc_and_init()).
Пусть это исключение имеет тип string
и строка, передаваемая обработчику, содержит описание ошибки. | ||||||
Просмотров: 4338 | Комментарии: 9 | | |
Всего комментариев: 2 | |||
| |||