Оператор try содержит три части:
□ контролируемый блок - составной оператор, предваряемый ключевым сло
вом try. В контролируемый блок включаются потенциально опасные операто
ры программы. Все функции, прямо или косвенно вызываемые из блока, так
же считаются ему принадлежащими;
□ один или несколько обработчиков исключений - блоков catch, в которых опи
сывается, как обрабатываются ошибки различных типов;
□ блок завершения finally выполняется независимо от того, возникла ошибка
в контролируемом блоке или нет.
Синтаксис оператора try:
try блок [ блоки catch ] [ блок finally ]
Отсутствовать могут либо блоки catch, либо блок finally, но не оба одновременно. Рассмотрим, каким образом реализуется обработка исключительных ситуаций.
1. Обработка исключения начинается с появления ошибки. Функция или опе
рация, в которой возникла ошибка, генерирует исключение. Как правило, ис
ключение генерируется не непосредственно в блоке try, а в функциях, прямо
или косвенно в него вложенных.
2. Выполнение текущего блока прекращается, отыскивается соответствующий
обработчик исключения, и ему передается управление.
|
|
3. Выполняется блок finally, если он присутствует (этот блок выполняется и в том
случае, если ошибка не возникла).
4. Если обработчик не найден, вызывается стандартный обработчик исключения. Его действия зависят от конфигурации среды. Обычно он выводит на экран окно с информацией об исключении и завершает текущий процесс.
Обработчики исключений должны располагаться непосредственно за блоком try. Они начинаются с ключевого слова catch, за которым в скобках следует тип обрабатываемого исключения. Можно записать один или несколько обработчиков в соответствии с типами обрабатываемых исключений. Блоки catch просматриваются в том порядке, в котором они записаны, пока не будет найден соответствующий типу выброшенного исключения.
Синтаксис обработчиков напоминает определение функции с одним параметром — типом исключения. Существуют три формы записи:
catch(тип имя) {.../* тело обработчика */ }
catch(тип) {.../* тело обработчика */ }
catch {... /* тело обработчика */ }
Первая форма применяется, когда имя параметра используется в теле обработчика для выполнения каких-либо действий, например вывода информации об исключении.
Вторая форма не предполагает использования информации об исключении, играет роль только его тип.
Третья форма применяется для перехвата всех исключений. Так как обработчики просматриваются в том порядке, в котором они записаны, обработчик третьего типа (он может быть только один) следует помещать после всех остальных. Пример:
try
|
|
{
//... // Контролируемый блок
}
catch (OverflowExceptione)
{
// Обработка исключений класса OverflowException (переполнение)
}
catch (DivideByZeroException)
{
//... // Обработка исключений класса DivideByZeroException (деление на 0)
}
catch
{
// Обработка всех остальных исключений
}
Если исключение в контролируемом блоке не возникло, все обработчики пропускаются.
В любом случае, произошло исключение или нет, управление передается в блок завершения finally (если он существует), а затем — первому оператору, находящемуся непосредственно за оператором try. В завершающем блоке обычно записываются операторы, которые необходимо выполнить независимо от того, возникло исключение или нет, например, закрытие файлов, с которыми выполнялась работа в контролируемом блоке, или вывод информации.
Операторы try могут многократно вкладываться друг в друга. Исключение, которое возникло во внутреннем блоке try и не было перехвачено соответствующим блоком catch, передается на верхний уровень, где продолжается поиск подходящего обработчика. Этот процесс называется распространением исключения.