Язык C++ позволяет программисту описывать обработку некоторых возникающих при работе программы ошибок, таких как переполнение, деление на ноль, попытка открыть несуществующий файл и прочих. При этом генерируется так называемое исключение, то есть объект специального вида, характеризующий возникшую в программе исключительную ситуацию. Он может также содержать в виде параметра некоторую уточняющую информацию. Особенностью исключений является то, что это сугубо временные объекты. Как только они обработаны каким-то обработчиком, они разрушаются.
Операторы, используемые для управления исключениями, имеют следующее формальное описание:
try
{
код, для которого выполняется обработка исключений
}
catch ( объявление_исключения )
{
код, выполняемый в случае возникновения исключения
}
throw выражение opt
Составной оператор, следующий после оператора try, определяет блок кода, для которого будет выполняться обработка исключений. Составной оператор, следующий после оператора catch, определяет блок кода, на который будет передано управление в случае возникновения исключения. Можно определять обработчики исключений как отдельно для каждого типа, включая и тип класса, так и общие для всех типов. Для того чтобы указать, что данный блок является обработчиком исключений для всех типов, в операторе catch в качестве объявление_исключения следует указать символ многоточия (…). Синтаксис оператора throw аналогичен синтаксису оператора return.
Схема управления исключениями выглядит следующим образом:
• оператор try указывает блок кода, для которого возможны возникновение и обработка исключений. Если при выполнении блока try не возникло ни одного исключения, то управление передается на первый оператор, следующий за блоком catch;
• оператор throw инициирует возникновение исключения. После его выполнения управление передается обработчику исключений;
• оператор catch указывает блок кода, называемый обработчиком исключений, обрабатывающий исключения конкретного типа. При возникновении исключения создается объект исключения. Поиск подходящего обработчика исключений выполняется сначала сверху вниз по всем блокам catch, указанным для текущего блока try, а затем вверх по иерархии объемлющих блоков try. Передача параметров обработчику исключения может выполняться как по значению, так и по ссылке. В первом случае инициализация формальных пара-метров выполняется копированием объекта исключения, а во втором – определением ссылки на объект исключения. После инициализации формальных параметров начинается процесс свертывания стека, включающий разрушение (и вызов деструкторов) для всех объектов, которые были созданы от начала блока try и до оператора, вызвавшего исключение. Разрушение происходит в порядке, обратном созданию этих объектов;
• по завершении обработки исключения управление передается на первый оператор после всех блоков catch, следующих за найденным блоком обработки исключений.
Например:
#include <iostream>
using namespace std;
int main()
{
char *buf;
try
{
buf = new char[512];
if( buf == 0 )
throw "Ошибка выделения памяти!";
}
//обработка исключения типа char*
catch( char * str )
{
cout << "Возникло исключение: " << str << '\n';
}
// ...
return 0;
}
Усложним пример:
#include <iostream>
using namespace std;
void MyFunc( void );
class CTest
{
public:
CTest(){};
~CTest(){};
const char *ShowReason() const
{ return "Исключение в классе CTest."; }
};
class CDemo
{
public:
CDemo();
~CDemo();
};
CDemo::CDemo()
{ cout << "Конструктор CDemo.\n"; }
CDemo::~CDemo()
{ cout << "Деструктор CDemo.\n"; }
void MyFunc()
{
CDemo D;
cout<< "MyFunc(): исключение CTest.\n";
throw CTest(); //генерируем исключение
}
int main()
{
cout << "main.\n";
try
{
cout << "try-секция, вызов MyFunc().\n";
MyFunc();
}
catch( CTest E )
{
cout << " catch-секция для типа CTest.\n";
cout << E.ShowReason() << "\n";
}
catch( char *str )
{
cout << " Возникло исключение: " << str <<"\n";
}
cout << "снова main.\n";
return 0;
}
В результате выполнения такой программы на дисплей будет выведено:
main.
try-секция, вызов MyFunc().
Конструктор CDemo.
MyFunc(): исключение CTest.
Деструктор CDemo.
catch-секция для типа CTest.
Исключение в классе CTest..
снова main.
Внутри блоков обработки исключений можно выполнять передачу объекта исключения следующему подходящему обработчику исключений. Передача исключения выполняется оператором throw без параметров. Например:
try
{
throw CSomeOtherException();
}
catch(...) // обработка всех исключений
{
// ...
// передача исключения другому обработчику исключений
throw;
}
|