Если к описанию особых ситуаций относиться не достаточно серьезно, то результатом может быть вызов unexpected(), что нежелательно во всех случая, кроме отладки. Избежать вызова unexpected() можно, если хорошо организовать структуру особых ситуации и описание интерфейса. С другой стороны, вызов unexpected() можно перехватить и сделать его безвредным.
Если компонент Y хорошо разработан, все его особые ситуации могут быть только производными одного класса, скажем Yerr. Поэтому, если есть описание
class someYerr : public Yerr { /* ... */ };
то функция, описанная как
void f() throw (Xerr, Yerr, IOerr);
будет передавать любую особую ситуацию типа Yerr вызывающей функции. В частности, обработка особой ситуации типа someYerr в f() сведется к передаче ее вызывающей f() функции.
Бывает случаи, когда окончание программы при появлении неожиданной особой ситуации является слишком строгим решением. Допустим функция g() написана для несетевого режима в распределенной системе. Естественно, в g() ничего неизвестно об особых ситуациях, связанных с сетью, поэтому при появлении любой из них вызывается unexpected(). Значит для использования g() в распределенной системе нужно предоставить обработчик сетевых особых ситуаций или переписать g(). Если допустить, что переписать g() невозможно или нежелательно, проблему можно решить, переопределив действие функции unexpected(). Для этого служит функция set_unexpected(). Вначале мы определим класс, который позволит нам применить для функций unexpected() метод "запроса ресурсов путем инициализации" :
typedef void(*PFV)(); PFV set_unexpected(PFV);
class STC { // класс для сохранения и восстановления PFV old; // функций unexpected() public: STC(PFV f) { old = set_unexpected(f); } ~STC() { set_unexpected(old); } };
Теперь мы определим функцию, которая должна в нашем примере заменить unexpected():
void rethrow() { throw; } // перезапуск всех сетевых // особых ситуаций
Наконец, можно дать вариант функции g(), предназначенный для работы в сетевом режиме: