Главная » Уроки по ООП » Урок 23. Класс Exception. Стандартные классы исключений. Операторы обработки исключений. |
ЛЕКЦИЯ |
Урок 23. Класс Exception. Стандартные классы исключений. Операторы обработки исключений.
Задание: составить краткую схему лекции, по которой можно будет рассказать, как обрабатывать исключительные ситуации и какие защитные конструкции имеются в языке программирования.
Исключительная ситуация как класс
Исключительная ситуация это такая ситуация, в результате которой генерируется ошибка, и выполнение программы прерывается. Например, деление на ноль - классический пример исключительной ситуации.
Как в такой ситуации действует человек? Если он пытается что-то сделать, и это не получается - он идёт другим путём. Так же и компьютер, следующий программе, умеющей обрабатывать исключительные ситуации. Он не бросает выполнение программы, не виснет, а обходит исключительную ситуацию, выполняя альтернативный вариант фрагмента, в которой исключительная ситуация возникла.
Возникает вопрос, почему бы не поставить проверку, например, на равенство нулю знаменателя при делении? Можно и поставить. Но во многих случаях источник исключительной ситуации далеко не так очевиден, а на все случаи жизни проверки не введёшь.
Итак, для контроля исключительных ситуаций программист должен подготовить как основной вариант фрагмента, где возможна исключительная ситуация, так и его вариант, в котором она заведомо невозможна, или выводится информационное сообщение для пользователя.
Под исключительной ситуацией мы будем понимать некое непредвиденное событие, способное повлиять на дальнейшее выполнение программы.
При обработке такой ситуации Delphi, как обычно, работает с объектами. С точки зрения компилятора Delphi исключительная ситуация - это объект.
Чем же различаются между собой исключительные ситуации? Как отличить одну исключительную ситуацию от другой? Поскольку это объекты, они отличаются классом (объектным типом). В модуле SYSUTILS.PAS описан объектный тип Exception. Он является предком для всех других объектов — исключительных ситуаций.
Тип Exception порождает многочисленные дочерние типы, соответствующие часто встречающимся случаям ошибок ввода/вывода, распределения памяти и т.п.
Исключительные ситуации |
Тип искл. ситуации |
Условие возникновения |
при работе с памятью | EOutOfMemory |
Недостаточно места в куче (памяти) |
EOutOfResources |
Нехватка системных ресурсов |
|
EInvalidPointer |
Недопустимый указатель (обычно nil) |
|
целочисленной математики | EDivByZero |
Попытка деления на ноль (целое число) |
ERangeError |
Число или выражение выходит за допустимый диапазон |
|
EIntOverflow |
Целочисленное переполнение |
|
математики с плавающей точкой | EInvalidOp |
Неверная операция |
EZeroDivide |
Попытка деления на ноль |
|
EOverflow |
Переполнение с плавающей точкой |
|
EUnderflow |
Исчезновение порядка |
|
EInvalidArgument |
Неверный аргумент математических функций |
Защитные конструкции
Для работы с объектами исключительных ситуаций существуют специальные конструкции языка Object Pascal — блоки try .. except и try .. finally. Они контролируют выполнение операторов, помещенных внутри блока до ключевого слова except или finally. В случае возникновения исключительной ситуации штатное выполнение вашей программы немедленно прекращается, и управление передается операторам, идущим за указанными ключевыми словами.
Хотя синтаксис двух видов блоков похож, но они принципиально отличаются назначением и решаемыми задачами.
Блок Try..Except
Вот как выглядит оператор контроля исключительных ситуаций:
try
{исполняемый код};
except
on Exception1 do {код, исполняемый в случае возникновения ошибки 1};
on Exception2 do {код, исполняемый в случае возникновения ошибки 2};
else
{код, обработчик всех не перехваченных ранее ошибок};
end;
Если при выполнении кода, размещенного в разделе try, генерируется исключение, то выполнение этого раздела прекращается и управление передается коду, размещенному в разделе except.
Раздел except может использоваться двумя способами.
- Во-первых, в нем могут располагаться любые операторы, кроме обработчиков исключений, начинающихся с приставки on. Это и операторы сообщения об ошибке, и команды, позволяющие освобождать системные ресурсы, а также другие операторы и команды.
- Во-вторых, раздел except используется для обработки исключений. В этом случае в него могут включаться только операторы обработки исключений. Если среди обработчиков встретился обработчик, соответствующий сгенерированному исключению, то выполняется оператор этого обработчика, исключение разрушается и управление передается коду, расположенному после оператора on Exception do.
Раздел, расположенный после ключевого слова else, служит для обработки любых исключений, не описанных в разделе except. Этот раздел не является обязательным. Если при обработке исключительной ситуации не будет найден подходящий обработчик, то произойдет обработка системным обработчиком исключений.
Пример: обработка исключительной ситуации деления на ноль.
а:=10;
b:=0;
try
c:=a/b;
except
on EZeroDivide do MessageBox('Делить на ноль нельзя!');
end;
Оператор on..do
Данный оператор находится внутри раздела except и может иметь две формы.
on <класс исключения> do <оператор>;
или
on <имя>: <класс исключения>
do <операторы, в которых можно использовать свойства исключения>
Например:
on EZeroDivide do MessageBox('Делить на ноль нельзя!');
Этот оператор обрабатывает только тот класс исключений, который в нем указан. При указании родительского (базового) класса, все классы исключений - потомки данного класса - также будут обработаны. Для обработки всех исключений можно обратиться к базовому классу всех исключений: Exception. После обработки исключения оно разрушается.
Вторая форма оператора on .. do отличается от первой тем, что данному исключению можно временно присвоить имя и обращаться к свойствам исключения. Обращаться к свойствам исключения можно с помощью конструкции <имя>.<имя свойства>.
Пример: обращения к свойствам исключения.
try
ScrollBar1.Max := ScrollBar1.Min - 1;
except
on E: EInvalidOperation do
MessageDlg( 'Игнорируем исключение: '- + E.Message, mtInformation, [mbOK], O)
end;
В приведенном примере мы присваиваем исключению EInvalidOperation временное имя Е. Затем в окне сообщения выводим текст ошибки E.Message, выдаваемый Delphi по умолчанию.
Команда Raise – регенерация исключений
Иногда, бывает необходимо, чтобы после обработки исключительной ситуации своим кодом вызывался стандартный обработчик ошибки. Например, в случае возникновения некоторой ошибки вы хотите, чтобы приложение сообщало пользователю какую-либо информацию, а затем передавало управление стандартному обработчику ошибок. Как вы уже знаете, после обработки исключения вашим кодом, исключение уничтожается. Для того чтобы самостоятельно вызвать снова это исключение, можно воспользоваться регенерацией исключений. Для регенерации исключения служит команда raise.
try
{ операторы }
except
on <класс исключения> do
begin
{операторы обработки исключения}
raise; // Регенерация исключения
end;
end;
После выполнения операторов обработки исключения, написанных программистом, выполняется команда raise, которая снова принудительно вызывает это исключение, после чего управление передается стандартному обработчику исключений.
Блок Try…Finally
Следующая конструкция try .. finally служит для защиты кода, записанного в разделе finally от исключительных ситуаций, которые в силу каких-либо причин могут происходить в разделе try.try
{операторы, способные создать исключительную ситуацию};
finally
{защищенные операторы, выполняемые в любом случае};
end;
Итак, операторы, которые размещены после ключевого слова finally, будут выполняться в любом случае, была сгенерирована исключительная ситуация или нет. Если в разделе try была сгенерирована исключительная ситуация, то управление немедленно передается разделу finally. Также, если исключительной ситуации в разделе, try не было, блок finally будет выполняться. Даже если в разделе finally произойдет ошибка, выполнение операторов этого раздела будет продолжено до конца.
В конструкции try .. finally не происходит обработка исключений, она используется в основном для освобождения ресурсов памяти, закрытия ненужных файлов и других операций освобождения ресурсов. Таким образом, в данной конструкции нуждаются операции с файлами, памятью, ресурсами Windows и объектами.
Вложенные исключительные ситуации
Молчаливые исключения
При разработке приложений на Delphi часто возникают ситуации, когда программисту не требуется обрабатывать исключения, а необходимо лишь прервать нежелательное действие, вызывающее ошибку. Для этого применяются так называемые молчаливые исключения. Молчаливые исключения являются потомками стандартного исключения EAbort.
ИС EAbort отличается тем, что для нее обработка по умолчанию не предусматривает вывода сообщений на экран.
Для того чтобы сгенерировать молчаливое исключение, можно вызвать процедуру Abort. Она автоматически сгенерирует исключение EAbort, которое прервет текущую операцию без вывода сведения об ошибке на экран.
Рассмотрим пример. Пусть форма содержит пустой список (ListBox1) и кнопку (Button1). Запишем в обработчик события кнопки onclick следующий код:
procedure TForm1.Button1Click(Sender: TObject);
var I: Integer;
begin
for I := 1 to 10 do (цикл 10 раз}
begin
ListBox1.Items.Add(IntToStr(I)); {добавляем номер в список}
if I = 7 then Abort; {прерываем добавление номеров в список после добавления седьмого}
end;
end;
В результате работы программы, после нажатия кнопки Button1, в список будет добавлено семь строк с номерами от 1 до 7.
Настройка Delphi – отключение реагирования на исключительные ситуации
При работе программы под управлением Delphi, система будет сама реагировать на исключительные ситуации, мешая работе операторов обработки исключений. Чтобы проверить их действие, можно запускать программу непосредственно из папки (exe-файл). Или можно отключить реакцию системы на исключительные ситуации, тем самым давая возможность отработать специально для этого написанным фрагментам программы - нашим операторам try/except/end. Для этого откроем пункт системного меню Delphi Tools -> Debugger Options.... В появившемся окошке нужно снять галку в чекбоксе Stop on Delphi Exceptions, расположенном на вкладке Language Exceptions. Теперь система Delphi будет предоставлять вашей программе возможность самостоятельно обрабатывать исключительные ситуации, среди которых могут быть и ситуации, возникновение которых прописано специально как удобный инструмент достижения необходимых результатов.
Составитель: Салий Н.А.