If (conditionB)

Исключительных ситуаций

Возбуждение нескольких

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

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

int AnyFunction()


{ if (conditionA)

// Если условие conditionA справедливо

throw "Big trouble!";

// функция возбуждает строковую

//ис­ключительную ситуацию с сообщением

// "Big trouble!".

// Если выполняется условие conditionB,

throw Overflow();

// функция посы­лает объект класса Overflow,

//создаваемый в данном случае с помощью

// обращения к конструктору класса по умолчанию

return 123;

// Если же функция не обнаружила ошибок,

//она возвращается обычным образом

}

Если условие conditionA справедливо (что бы оно ни значило), функция возбуждает строковую ис­ключительную ситуацию с сообщением "Big trouble!". Если выполняется условие conditionB, функция посы­лает объект класса Overflow, создаваемый в данном случае с помощью обращения к конструктору класса по умолчанию. Если же функция не обнаружила ошибок, она возвращается обычным образом, передавая значение 123 тому, кто ее вызвал.

следствия из приведенного примера.

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

• Возбуждение исключительной ситуации немедленно завершает выполнение функции, в которой выполняется оператор throw.

• исключительные ситуации обеспечивают альтернативный механизм возврата для функций.

Последнее замечание — ключевое. Функция AnyFunctionO обычно возвращает целочисленное значение, однако, если возникает исключительная ситуация она возвращает строку или объект класса Overflow. Только операторы catch могут воспринять эти возвращаемые значения. Если исключительных ситуаций не возникло, функция завершается нормально, возвращая (необязательно) значение типа, с которым объявляется функция, обратно оператору вызова этой функции.

 

можно поддерживать несколько типов объектов исключительных ситуаций с помощью серии операто­ров catch. Например, для обработки исключительных ситуаций для класса Error и строк следующие операторы catch один за другим:

catch (Error e) {

// Обработка исключительной ситуации для класса Error }

catch (const char* message) {

// Обработка исключительной ситуации для строк }

Введение в блоки try

Теперь настало время для изучения еще одной премудрости — блоков try, которые, кажется, смущают лю­бого, кто только начал ими пользоваться.

Для того чтобы принимать объекты исключительных ситуаций неко­торой функции, вызовите ее внутри блока try:

try {

//Блок try содержит один или несколько //операторов, исключительные ситуации //которых надо перехватывать.

//

int x = AnyFunction();

// Если в функции AnyFunction //возникла исключительная ситуация, //блок try немедленно завершается.

}

catch (Error e) {

//после блока try следует поместить //один или несколько операторов catch, //перехватывающих все //исключительные ситуации, //возбуждаемые операторами в try.

//если ф-ция возбудила //исключительную ситуацию

e.Report();

//вызов ф-цию Report();

//объекта Error

exit(-1);

//прервать

}

Блок try содержит один или несколько операторов, исключительные ситуации которых вы хотите перехватывать. Один или более операторов catch должны следовать за блоком try. Это похоже на ситуацию, когда иг­рок разбегается, чтобы пробить пенальти, а вратарь готовится отразить удар. В любом случае, после блока try следует поместить один или несколько операторов catch, перехватывающих все исключительные ситуации, возбуждаемые этими операторами.

 

Несколько блоков try и соответствующих им операторов catch м.б. объявлены вложенными, хотя синтаксис в этом случае может привести к запутанному коду.

Например,

try {

FunctionAO; try {

FunctionBO; catch (Error e) {

e.ReportO; // ReportO

catch (Error e) { e.ReportO;}

Использование блоков try

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

try {

cout « "Hello!" << endl;

int x = AnyFunction();

//Если в функции AnyFunction //возникла исключительная ситуация, //блок try немедленно завершается.

//любое условие исключительной //ситуации при­водит к пропуску //присваивания х и завершающего //оператора вывода.

cout « "x == " « x « endl; }

В блоке try сначала отображается сообщение. Затем в нем вызывается функция AnyFunctionO, результат которой присваивается целочисленной переменной х. Если в функции AnyFunction возникла исключительная ситуация, блок try немедленно завершается. Другими словами, любое условие исключительной ситуации при­водит к пропуску присваивания х и завершающего оператора вывода.

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

За блоком try должны следовать один или несколько операторов catch (иначе не имеет смысла использо­вать try). Вот более законченный пример того, как можно обработать несколько исключительных ситуаций, которые может возбудить функция, подобная AnyFunctionO:

try {

cout « "Here we go!" « endl;

int x = AnyFunctionO;

cout « "x.== " « x << endl;

}

//Если исключительных ситуаций не //было, оба оператора catch пропус­//каются, т.к. нет объектов //исключительных ситуаций //объявленных типов, которые нужно //было бы пере­хватывать.

catch (char* message) {

cout << "Error! -- " << message « endl;

exit(-1); // Необязательно }

catch (Overflow) {

cout « "Overflow!" « endl;

exit(-1);// Необязательно

}

// В этом месте программа //продолжает выполнение

// как обычно

В этом более пространном коде сначала испытывается вызов функции AnyFunctionO. Если функция за­вершилась нормально, ее результат присваивается переменной х, которая отображается в следующем операто­ре записи в стандартный поток вывода. Если исключительных ситуаций не было, оба оператора catch пропус­каются, поскольку нет объектов исключительных ситуаций объявленных типов, которые нужно было бы пере­хватывать. Конечно, если функция AnyFunctionO возбуждает исключительную ситуацию, выполнение блока try немедленно прерывается, посланные объекты перехватываются соответствующими операторами catch, a именно тем из них, в котором объявлен параметр типа, соответствующего типу данных посланного объекта.

В данном примере в операторах catch вызывается библиотечная функция exitO для аварийного заверше­ния программы. Приведенная реакция не обязательна — вам предоставляется самому решать, что делать в от­вет на возбуждение исключительной ситуации.

Вы можете вставить один, два, три или более операторов catch после блока try для обработки ис­ключительных ситуаций различных типов. В этом примере два оператора catch обрабатывают исключитель­ные ситуации для строк и класса Overflow. Любые другие типы исключительных ситуаций, не обрабатывае­мые операторами catch, передаются вверх по цепочке вызовов. Например, предположим, что функция AnyFunction также возбуждает исключительную ситуацию типа NewException. Если в функции g() был вы­зван упомянутый выше код, объект этой исключительной ситуации будет передаваться наверх в g(), так как в этом коде обрабатываются только исключительные ситуации типов char* и Overflow.

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