Для того чтобы повторно сгенерировать исключение в его обработчике, воспользуйтесь throw-инструкцией без указания типа исключения. В этом случае текущее исключение будет передано во внешнюю try/catch-последовательность. Чаще всего причиной для такого выполнения инструкции throw служит стремление позволить доступ к одному исключению нескольким обработчикам. Например, первый обработчик исключений будет сообщать об одном аспекте исключения, а второй — о другом. Исключение можно повторно сгенерировать только в catch-блоке (или в любой функции, вызываемой из этого блока). При повторном генерировании исключение не будет перехватываться той же catch-инструкцией. Оно распространится на ближайшую try/catch-последовательность.
Повторное генерирование исключения демонстрируется в следующей программе (в данном случае повторно генерируется тип char *).
// Пример повторного генерирования исключения.
#include <iostream>
using namespace std;
void Xhandler()
{
try {
throw "Привет"; // генерирует исключение типа char *
}
catch(char *) { // перехватывает исключение типа char *
cout << "Перехват исключения в функции Xhandler.\n";
throw; // Повторное генерирование исключения типа char *, которое будет перехвачено вне функции Xhandler.
}
}
int main()
{
cout << "НАЧАЛО\n";
try {
Xhandler();
}
catch(char *) {
cout << "Перехват исключения в функции main().\n";
}
cout << "КОНЕЦ";
return 0;
}
При выполнении эта программа генерирует такие результаты.
НАЧАЛО
Перехват исключения в функции Xhandler.
Перехват исключения в функции main().
КОНЕЦ
В главе 9 вы узнали, что оператор new генерирует исключение, если не удается удовлетворить запрос на выделение памяти. Поскольку тема исключений рассматривается только в этой главе, описание обработки исключений этого типа было отложено "на потом". Вот теперь настало время об этом поговорить.
Для начала необходимо отметить, что в этом разделе описывается поведение оператора new в соответствии со стандартом C++. Как было отмечено в главе 9, действия, выполняемые системой при неуспешном использовании оператора new, с момента изобретения языка C++ изменялись уже несколько раз. Сначала оператор new возвращал при неудаче значение null. Позже такое поведение было заменено генерированием исключения. Кроме того, несколько раз менялось имя этого исключения. Наконец, было решено, что оператор new будет генерировать исключения по умолчанию, но в качестве альтернативного варианта он может возвращать и нулевой указатель. Следовательно, оператор new в разное время был реализован различными способами. И хотя все современные компиляторы реализуют оператор new в соответствии со стандартом C++, компиляторы более "почтенного" возраста могут содержать отклонения от него. Если приведенные здесь примеры программ не работают с вашим компилятором, обратитесь к документации, прилагаемой к компилятору, и поинтересуйтесь, как именно он реализует функционирование оператора new.
Согласно стандарту C++ при невозможности удовлетворить запрос на выделение памяти, требуемой оператором new, генерируется исключение типа bad_alloc. Если ваша программа не перехватит его, она будет досрочно завершена. Хотя такое поведение годится для коротких примеров программ, в реальных приложениях необходимо перехватывать это исключение и разумно обрабатывать его. Чтобы получить доступ к исключению типа bad_alloc, нужно включить в программу заголовок <new>.
Рассмотрим пример использования оператора new, заключенного в try/catch-блок для отслеживания неудачных результатов запроса на выделение памяти.