
- •Глава 7.
- •Перехват и обработка исключений
- •Возобновление исключения
- •Доступ к аргументам исключения
- •Последовательность обработки исключения
- •Обработка объекта исключения (Ex7_1)
- •Спецификация исключений
- •Уничтожение локальных переменных при обработке исключения (Ex7_2)
- •Уничтожение локальных переменных при обработке исключения (2)
- •Результат
- •Обработка непредусмотренных исключений
- •Завершающая обработка (Ex7_3)
- •7.2 Механизм структурного управления
- •Получение информации об исключении
- •Получение информации об исключении (2)
- •Обработка аппаратных и программных исключений Windows (Ex7_4)
- •Генерация исключений в С
- •Завершающая обработка
- •Совместное использование обычной и завершающей обработки исключений (Ex7_5)
- •7.3 Совместное использование различных механизмов обработки исключений
- •Пример совместного использования механизмов исключения (Ex7_6)
- •Пример совместного использования
- •Трансляция структурных исключений (Ex7_7)
- •Трансляция структурных исключений (2)

Глава 7.
Исключения
МГТУ им. Н.Э. Баумана Факультет Информатика и системы управления
Кафедра Компьютерные системы и сети Лектор: д.т.н., проф.
Иванова Галина Сергеевна
1

7.1 Механизм исключений С++
В С и С++ используются разные стандарты обработки исключений.
Генерация исключений:
throw [<Тип>](<Аргументы>);
где <тип> – тип (чаще класс) генерируемого значения; если тип не указан, то компилятор определяет его исходя из типа аргумента (обычно это один из встроенных типов);
<аргументы> – одно или несколько выражений, значения которых будут использованы для инициализации генерируемого объекта.
Примеры:
throw (”Неверный параметр”); /* тип const char * с указанным в кавычках значением */
throw (221); /* тип const int с указанным значением */
class E { //класс исключения |
|
public: int num; |
// номер исключения |
E(int n): num(n){} |
// конструктор класса |
} |
|
… |
2 |
throw E(5); // класс E |

Перехват и обработка исключений
try {<Защищенный код>}
catch (<Ссылка на тип>){<Обработка исключений>} При этом:
1)исключение типа T будет перехватываться обработчиками типов T, const T, T& или const T&;
2)обработчики типа базового класса перехватывают исключения типа производных классов;
3)обработчики типа void* перехватывают все исключения типа указателя.
Блок catch, для которого в качестве типа указано «…» обрабатывает исключения всех типов.
Примеры:
try {<Операторы>} // выполняемый фрагмент программы catch (EConvert& A){<Операторы>} /* перехват исключений
типа EConvert */
catch (char* Mes){<Операторы>} //перехват исключений char*
< > 3
catch(…) { Операторы } //перехват остальных исключений

Возобновление исключения
Если перехваченное исключение не может быть обработано, то оно возобновляется.
Пример:
class |
E{}; |
// класс исключения |
void somefunc() |
|
|
{ |
if(<условие> throw Out(); }// генерация исключения |
void func()
{try { somefunc(true); }
catch(E& e){ if (<условие>) throw; } /* если здесь исключение обработать нельзя, то возобновляем его */ }
void mainfunc()
{try { func();}
catch(E& e){ … } } // здесь обрабатываем исключение
4


Доступ к аргументам исключения
Использование имени переменной в качестве параметра оператора catch позволяет операторам обработки получить доступ к аргументам исключения через указанное имя.
Пример: |
|
|
class E //класс исключения |
|
|
{ public: int num; |
// номер исключения |
|
E(int n): num(n){} |
// конструктор |
|
} |
|
|
… |
|
|
try { ... |
|
|
throw E(5); |
// генерируемое исключение |
...}
catch (E& e){if (e.num==5) {…}} // получен доступ к полю
5


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

Обработка объекта исключения (Ex7_1)
#include "stdafx.h" #include <stdio.h> class MyException
{protected: int nError;
public: MyException(int nErr) {nError=nErr;}
~MyException(){puts("destructor");}
void ErrorPut(){printf("Error %d.\n",nError);}
};
int main(int argc, char* argv[])
{
try
{
throw MyException(5);
}
catch(MyException E){E.ErrorPut();} puts("program");
return 0;
}
destructor
Error 5. destructor destructor program
Press any key to continue
7

Спецификация исключений
При объявлении функции можно указать, какие исключения она может генерировать:
throw(<тип>,<тип>…). Пример:
void func() throw(char*,int){…} /*функция может генерировать исключения char* и int */
Спецификация исключений не считается частью типа функции и, следовательно, ее можно изменить при переопределении:
class ALPHA
{public: struct ALPHA_ERR{};
virtual void vfunc() throw(ALPHA_ERR){}
};
class BETA : public ALPHA { public:
|
void vfunc() throw(char *) {} |
8 |
}; |
|
|
|
|

Уничтожение локальных переменных при обработке исключения (Ex7_2)
#include "stdafx.h" |
При «раскручивании» стека |
#include <iostream.h> |
локальные переменные |
void MyFunc( void ); |
уничтожаются |
|
|
class CTest |
|
{public: CTest(){}; |
|
~CTest(){};
const char *ShowReason() const
{ return "Exception in CTest class."; }
};
class CDtorDemo {public: CDtorDemo();
~CDtorDemo();
};
CDtorDemo::CDtorDemo()
{cout << "Constructing CDtorDemo." << endl;}
CDtorDemo::~CDtorDemo()
9
{ cout << "Destructing CDtorDemo." << endl;}

Уничтожение локальных переменных при обработке исключения (2)
void MyFunc() {CDtorDemo D;
cout<<"In MyFunc().Throwing CTest exception."<<endl; throw CTest();
}
int main()
{cout << "In main." << endl; try
{cout<<"In try block, calling MyFunc()."<<endl; MyFunc(); }
catch(CTest E)
{cout << "In catch handler." << endl; cout << "Caught CTest exception type: ";
cout << E.ShowReason() << endl;
}
catch( char *str )
{cout<<"Caught other exceptions: "<<str<<endl;} cout<<"Back in main. Execution resumes here."<<endl;
return 0;} |
10 |