Перехват исключений

Когда с помощью throw генерируется исключение, функции исполнительной библиотеки C++ выполняют следующие действия:

1) создают копию параметра throw в виде статического объекта, который существует

до тех пор, пока исключение не будет обработано;

2) в поисках подходящего обработчика раскручивают стек, вызывая деструкторы

локальных объектов, выходящих из области действия;

3) передают объект и управление обработчику, имеющему параметр, совместимый

по типу с этим объектом.

При раскручивании стека все обработчики на каждом уровне просматриваются

последовательно, от внутреннего блока к внешнему, пока не будет найден подходящий

обработчик.

Обработчик считается найденным, если тип объекта, указанного после throw:

• тот же, что и указанный в параметре catch (параметр может быть записан в форме Т, const Т, Т& или const Т&. где Т— тип исключения);

• является производным от указанного в параметре catch (если наследование производилось с ключом доступа public);

• является указателем, который может быть преобразован по стандартным правилам

преобразования указателей к типу указателя в параметре catch.

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

Рассмотрим пример:

// File TEST1.CPP

#include <iostream>

#include <fstream>

using namespace std;

class Hello

{

// Класс, информирующий о своем создании и уничтожении

public:

Hello(){cout << "Hello!" << endl;}

~Hello(){cout << "Bye!"<< endl;}

};

void f1()

{

setlocale(LC_ALL, "Russia");

ifstream ifs("\\INVALID\\FILE\\NAME");

if (ifs.fail())

{

cout << "Генерируем исключение"<< endl;

throw "Ошибка при открытии файла";

}

}

// Создаем локальный объект

// Вызываем функцию. генерирующую исключение

void f2()

{

Hello Н;

f1();

}

int main()

{

setlocale(LC_ALL, "russian");

try

{

cout << "Входим в try-блок"<< endl;

f2();

cout<< "Выходим из try-блока" << endl;

}

catch(int i)

{

cout << "Вызван обработчик int. исключение - " << i << endl;

return -1;

}

catch (const char * p)

{

cout<< "Вызван обработчик const char*, исключение - "

<< p << endl;

return -1;

}

catch(...)

{

cout << "Вызван обработчик всех исключений" << endl;

return -1;

}

return 0; // Все обошлось благополучно

}

Результаты выполнения программы:


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: