Лекция 15. Обработка исключительных ситуаций


Существует категория ошибок, которые не способны выявить препроцессоры, трансляторы и программы сборки. К их числу относятся так называемые ошибки времени выполнения. Эти ошибки проявляются в ходе выполнения программы.

Ошибки времени выполнения, возникающие непосредственно в ходе выполнения программы, в терминах объектно-ориентированного программирования называются исключительными ситуациями. Исключительные ситуации — это события, которые прерывают нормальный ход выполнения программы.

Различают синхронные и асинхронные исключительные ситуации.

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

Асинхронные исключительные ситуации непосредственно не связаны с выполнением программы. Их причинами могут служить аппаратно возбуждаемые прерывания (например, сигналы от таймера), сообщения, поступающие от внешних устройств или даже от локальной сети.

Реакция на исключительную ситуацию называется исключением.

Заметим, что исключительная ситуация не всегда неожиданна. Очень часто при разработке алгоритма уже закладывается определенная реакция на вероятную ошибку.

Например, функция, размещающая целочисленные значения в массиве по определенному индексу, может самостоятельно следить за допустимыми значениями индекса. Она возвращает единицу в случае успешного размещения значения и нуль, если значение параметра, определяющего индекс, не позволяет этого сделать.

Существует целый ряд проблем, связанных с подобным способом организации программного кода. Рассмотрим некоторые из них.

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

С ростом числа вариантов возвращаемых значений становится все более актуальной проблема разделения «положительных» и «отрицательных» ответов.

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

Наконец, конструкторы и деструкторы вообще не возвращают никаких значений. Поэтому они не способны сообщить о своих проблемах общепринятым способом. Для них приходится специально изобретать особые нестандартные средства взаимодействия.

В C++ имеются встроенные средства для их возбуждения и обработки. С помощью этих средств активизируется механизм, позволяющий двум несвязанным (или независимо разработанным) фрагментам программы обмениваться информацией об исключении.

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

Возбуждение (или генерация) исключения обеспечивается операцией throw. Оператор возбуждения исключения является полноправным оператором и в принципе может располагаться в любом месте программы. Его выполнение за пределами контролируемого блока приводит к завершению процесса выполнения программы.

Операция throw может применяться в сочетании с операндом, каковым может оказаться выражение произвольного типа и значения.

Оператор, построенный на основе такого выражения, можно называть генератором исключения. А его место расположения обычно называют точкой генерации. Вот примеры разнообразных генераторов исключений:

throw 1;throw "Это сообщение об исключении…";throw 2*2*fVal;throw (int)5.5;throw (ComplexType)125.96;/*Разумеется, если определен соответствующий конструкторпреобразования или функция приведения.*/

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

throw NULL;throw (void *) &iVal;

Обычно генератор исключения используется в сочетании с try-блоком (контролируемым блоком). Их взаимодействие обеспечивается через стек вызова. Поэтому точка генерации исключения должна располагаться в теле функции, непосредственно или косвенно вызываемой из множества операторов данного try-блока. Такой блок начинается с ключевого слова try, за которым идет последовательность инструкций, заключенная в фигурные скобки, а после этого — список обработчиков, называемых catch-предложениями. Try-блок группирует инструкции программы и ассоциирует с ними обработчики исключений.

try { Оператор; Оператор; Оператор; }СписокРеакций

Это блок операторов, то есть, составной оператор. Его место — тело функции. Этот оператор может входить в любой другой блок операторов.

Он начинается с ключевого слова try (поэтому дальше мы его будем называть try-блоком), следом за которым располагается так называемый блок испытания. В блоке испытания обычно размещается критический код, выполнение которого может привести к возникновению ошибки времени выполнения.

За ним следует, по крайней мере, один элемент списка реакций со своим блоком перехвата. Каждый блок перехвата начинается с заголовка — ключевого слова catch, за которым в круглых скобках располагается объявление ситуации. Синтаксис объявления ситуации напоминает объявление параметра в прототипе функции. Catch-блок содержит код, предназначенный для перехвата исключений.

Вернемся к примеру с классом CStack. Метод pop возвращал значение 0 в случае попытки выталкивания из пустого стека. В случае успеха значение возвращалось через параметр функции. Более естественен способ, когда функция возвращает необходимое значение, а при попытке выталкивания из пустого стека возбуждается исключение. Операция throw будет возвращать экземпляр класса StackException,

Файл CSstak.h…………#include <string.h>class StackException{public: char mes[256]; StackException(char* m) {strcpy(mes, m);}};template <class Type>class CStack { ……………………… Type pop(void); ………………………};template <class Type> ………………………Type CStack<Type>::pop(void){ if (isempty()) throw StackException("Stack is empty"); return data[--top];} ………………………Тестирующая программа:#include <iostream.h>#include "CStack.h"int main(int argc, char* argv[]){ CStack <int> stack(10); int a; for (int i=0;i<5;i++) stack.push(i); try { for (int i=0;i<6;i++) { a=stack.pop(); cout<<a<<endl; } } catch ( StackException e) { cout<<e.mes<<endl; } cin>>a; return 0;}

Программа выводит следующие данные:

43210Stack is empty

catch-блок вида catch(…) перехватывает все виды исключений (ранее не перехваченные).

catch (...){ cout<<"unknown exception"<<endl;}


Дата добавления: 2016-07-27; просмотров: 3607;


Поиск по сайту:

Воспользовавшись поиском можно найти нужную информацию на сайте.

Поделитесь с друзьями:

Считаете данную информацию полезной, тогда расскажите друзьям в соц. сетях.
Poznayka.org - Познайка.Орг - 2016-2024 год. Материал предоставляется для ознакомительных и учебных целей.
Генерация страницы за: 0.008 сек.