Возможны случаи, когда обработчик, перехватив возникшее исключение,
может решить, что он либо не может обработать это исключение, либо может
обработать его только частично. В таких случаях обработчик исключения может
передать обработку исключения (возможно, частично) другому обработчику.
Это достигается путем перебрасывания исключения исполнением оператора
throw;
Вне зависимости от того, способен ли обработчик обслужить исключение
(хотя бы частично), он может перебросить его для дальнейшей обработки во
внешнем коде. Следующий охватывающий try-блок детектирует
переброшенное исключение, которое попытается обслужить обработчик,
ассоциированный с этим try-блоком.
Программа на рис. 16.3 демонстрирует перебрасывание исключения.
В try-блоке функции main (строки 32-37) строка 35 вызывает функцию
throwException (строки 11-27). Эта функция также содержит try-блок
(строки 14-18), из которого оператор throw в строке 17 выбрасывает объект класса
стандартной библиотеки exception. Обработчик catch в функции
throwException (строки 19-24) перехватывает исключение, печатает сообщение об
ошибке (строки 21-22) и перебрасывает исключение (строка 23). При этом функция
throwException завершается и управление возвращается к строке 35 блока
try...catch в main. Блок try завершается (т.е. строка 36 не исполняется) и
исключение перехватывается catch-обработчиком в main (строки 38-41),
который печатает сообщение об ошибке (строка 40). [Замечание. Поскольку мы
здесь не используем в catch-обработчиках параметры-исключения, то не
указываем имена параметров, а только тип исключения, который нужно
перехватить (строки 19 и 38).]
// Рис. 16.3: TEST3.cpp
// Демонстрация переброса исключения.
#include <iostream>
using std::cout;
using std::endl;
#include <exception>
using std::exception;
// выбросить, перехватить и перебросить исключение
void throwException()
{
// выбросить исключение и немедленно перехватить его
try
{
cout << " Function throwException throws an exception\n";
throw exception(); // генерировать исключение
} // конец try
catch (exception &) // обработать исключение
{
cout << " Exception handled in function throwException"
<< "\n Function throwException rethrows exception";
throw; // перебросить исключение для дальнейшей обработки
} // конец catch
cout << "This also should not print\n";
} // конец функции throwException
int main ()
{
// выбросить исключение
try
{
cout << "\nmain invokes function throwException\n";
throwException();
cout << "This should not print\n";
} // конец try
catch (exception &) // обработать исключение
{
cout << "\n\nException handled in main\n";
} // конец catch
cout << "Program control continues after catch in main\n";
return 0;
} // конец main
/*
main invokes function throwException
Function throwException throws an exception
Exception handled in function throwException
Function throwException rethrows exception
Exception handled in main
Program control continues after catch in main
*/
Спецификации исключений (не поддерживается MS VS2008)
Необязательная спецификация исключений (или список throw)
перечисляет исключения, которые могут выбрасываться функцией. Рассмотрим,
например, следующее объявление функции:
int someFunction(double value)
throw (ExceptionA, ExceptionB, ExceptionC)
{
// тело функции
}
В этом определении спецификация исключений, которая начинается
ключевым словом throw непосредственно вслед за закрывающей скобкой списка
параметров функции, указывает, что someFunction может выбрасывать
исключения типов ExceptionA, ExceptionB и ExceptionC. Функции разрешается
выбрасывать только исключения типов, перечисленных в спецификации, или
любых производных от них. Если функция выбрасывает исключение, не
принадлежащее к специфицированному типу, вызывается функция unexpected,
которая обычно завершает программу.
Функция, не определяющая спецификацию исключений, может
выбрасывать любые исключения. Размещение после списка параметров throw() —
пустой спецификации исключений — указывает, что функция не выбрасывает
исключений. Если такая функция пытается выбросить исключение, вызывается unexpected. В разделе 16.7 показано, каким образом можно изменить
поведение функции unexpected посредством вызова set__unexpected.