Подробности - Исключительные ситуации

Знакомство с исключительными ситуациями начнем с примера:

#include "iostream.h"
#include "afxwin.h"

void funct1();
void funct2();
void funct3();


void main()
{
	try
	{
		funct1();
		funct2();
		funct3();
	}
	catch(CString cs)
	{
		cout << "Error Detecting" << endl;
		cout << cs << endl;
	}
}


void funct1()
{
}

void funct2()
{
	CString s="Error funct 2";
	int x;
	cin >> x;
	if (x==1) throw (s);
}

void funct3()
{
}

Создавайте приложение Win32 Console запускайте. Программа попросит ввести Вас число. Если Вы введете 1, то увидите на экране:

1
Error Detecting
Error funct 2
Press any key to continue

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

Давайте введем термин исключительная ситуация. Исключительная ситуация - это ситуация в программе требующая специальной обработки. А вот под специальной ситуацией можно понимать разные вещи. Например нельзя открыть файл или ошибка соеднинения. Вопрос этот тонкий, и как мне кажется каждый должен решать сам, что в Вашей программе является исключительной ситуацией. Рассмотрим условный пример.

Условный пример. Ваша программа должна установить связь с базой данный используя ODBC.

Database db;		// объект базы данных
db.Open("x.db");		// имя файла
db.OpenTable("table1");	// имя таблицы

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

Выходы из этой ситуации придуманы давно. Заводить переменную как флаг ошибки и обрабатывать её.

Вот так например

Database db;	
if (db.Initial())
{
	db.Open("x.db");	
	if (db.Open())
	{
		if (db.OpenTable("table1"))
		{
		}	
	}
}

Но еще ошибку надо проверить на тип, например отсутсвует файл или нет доступа. И всё это в коде функции, обрастая if , case и т.д. не тяжело и потерять смысл, о чем вообще функция :-).

Обработка исключительных ситуаций позволяет крассиво решить эту проблемму. Вот так:

try
{
	Database db;				
	db.Open("x.db");			
	db.OpenTable("table1");		
}
catch(...)
{
	cout << "Error detected " << end;
}

Как видите обработка ошибок стекается в одну функцию. Внимание для того чтобы пользоваться этими возможностями функции классы должны быть ориентированны на обработку исключительных ситуаций. Обработка исключительных ситуаций входит в стандарт ANSI C++, и её должны поддерживать компиляторы. Ниже приведен пример, который работает на VC++ 5.

#include "iostream.h"
#include "afxwin.h"

void main()
{
	try
	{
		int x=1;
		int y=0;
		x=x/y;
		cout << " Hello bad cod ";
	}
	catch(...)
	{
		cout << "Error detecting" << endl;
	}
}

При выполнении этой программы программа не завершится ошибкой Windows, и надпись Hello bad cod Вы не увидите. На экране будет зловещее Error detecting. Но реакция на ошибку в Вашей власти.

Итак давайте разберемся с обьявлениями. Защищается блок кода так.

try
{
	// защищаемый код
}
catch(...)
{
	// реакция на ошибку
}

Если Вам самом необходимо вызвать исключительную ситуацию Воспользуйтесь throw:

// Действие
// Если ошибка вызвать
throw "Error"

Обработка ошибок и из вызов основаны на классах. В примере ниже вы получите abnormal terminated так как тип возбуждаемой ошибки не соответсвует классу обработки. throw type_error и catch (type_error) должны совпадать.

#include "iostream.h"
#include "afxwin.h"
void main()
{
	try
	{

		throw 23.34;
	}
	catch(int i)
	{
		cout << "Error detecting" << endl;
	}
}

Для обработки этой ошибки необходимо обьявить catch(double i)

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


Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Каев Артем - 03.10.99