По возможности возбуждайте объекты типа error
Листинг 15 показывает простую систему определений класса для возбуждения исключений. Я могу перехватить ошибки чтения или записи подобным образом:
try
{
file f("name", "rw");
buffer b;
b = f.read();
f.write( b );
}
catch( file::open_error r )
{
// Файл не существует или не может быть открыт.
}
catch( file::io_error r )
{
// Какая-то из неисправимых ошибок ввода/вывода.
}
Если меня волнует лишь то, что произошла ошибка определенного вида, и не волнует, какого конкретно, то я могу сделать так:
file f;
try
{
buffer b;
b = f.read()
f.write( b );
}
catch( file::error r )
{
// ...
}
Листинг 15. Классы исключений
class file
{
public:
class error {};
class open_error : public error {};
class io_error : public error {};
/p>
// ...
}
Этот код работает, потому что объект file::read_error
является объектом типа file::error
(так как относится к производному классу). Вы всегда можете перехватить объект производного класса, используя ссылку или указатель базового класса.
Я мог бы также предложить другой класс, использующий тот же самый механизм:
class long_double
{
public:
class error {};
class didvide_by_zero : public error {};
// ...
};
Так как классы error являются вложенными определениями, то именами на самом деле являются file::error и long_double::error, поэтому здесь нет конфликта имен.
Для упрощения сопровождения я всегда использую error в качестве своего базового класса для исключений. (Я не мог использовать производный класс, даже если здесь был бы возможен всего один вид ошибки). Таким образом, я знаю, что, имея возбуждающий исключение класс some_class, можно перехватить это исключение при помощи:
catch(some_class::error r)
Эту ошибку искать не придется. Если применяется наследование, то я использую базовый класс error
таким образом:
class employee
{
public:
class error {};
class database_access_error : public error {};
};
class peon : public employee
{
class error : public employee::error {};
class aagh : public error {};
};
Этим способом исключение aagh
может быть перехвачено как peon::aagh, peon::error
или employee::error.
Нет смысла создавать класс глобального уровня error, от которого наследуются все локальные классы error, потому что для обработки этой ситуации вы можете использовать обработчик catch(…).