Механизм исключительных ситуаций предоставляет гибкие возможности для обработки ошибок, однако им надо уметь правильно пользоваться. В этом параграфе мы рассмотрим некоторые приемы обработки исключительных ситуаций.
Прежде всего, имеет смысл определить для них специальный класс. Простейшим вариантом является класс, который может хранить код ошибки:
class Exception { public : enum ErrorCode { NO_MEMORY, DATABASE_ERROR, INTERNAL_ERROR, ILLEGAL_VALUE }; Exception(ErrorCode errorKind, const String&errMessage); ErrorCode GetErrorKind(void )const {return kind;}; const String&GetErrorMessage(void )const {return msg;}; private : ErrorCode kind; String msg; };
Создание исключительной ситуации будет выглядеть следующим образом:
if (connect(serverName)==false ) throw Exception(Exception::DATABASE_ERROR, serverName);
А проверка на исключительную ситуацию так:
try { ... }catch (Exception&e){ cerr <<"Произошла ошибка "<<e.GetErrorKind() <<"Дополнительная информация:" <<e.GetErrorMessage(); }
Преимущества класса перед просто целым числом состоят, во-первых, в том, что передается дополнительная информация и, во-вторых, в операторах catch можно реагировать только на ошибки определенного вида. Если была создана исключительная ситуация другого типа, например
throw AnotherException;
то блок catch будет пропущен: он ожидает только исключительных ситуаций типа Exception . Это особенно существенно при сопряжении нескольких различных программ и библиотек – каждый набор классов отвечает только за собственные ошибки.
В данном случае код ошибки записывается в объекте типа Exception . Если в одном блоке catch ожидается несколько разных исключительных ситуаций, и для них необходима разная обработка, то в программе придется анализировать код ошибки с помощью операторов if или switch .
try { ... }catch (Exception&e){ cerr <<"Произошла ошибка "<<e.GetErrorKind() <<"Дополнительная информация:" <<e.GetErrorMessage(); if (e.GetErrorKind()==Exception::NO_MEMORY || e.GetErrorKind()== Exception::INTERNAL_ERROR) throw ; else if (e.GetErrorKind()== Exception::DATABASE_ERROR) return TRY_AGAIN; else if (e.GetErrorKind()== Exception::ILLEGAL_VALUE) return NEXT_VALUE; }