обработчика не существует, то управление передается в функцию terminate(),
определенную в стандартной библиотеке C++.
Try-блок может содержать любую инструкцию языка
C++: как выражения, так и объявления. Он вводит локальную
область видимости, так что объявленные внутри него переменные
недоступны вне этого блока, в том числе и в catch-обработчиках.
Например, функцию main() можно переписать так, что объявление переменной
stack окажется в try-блоке. В таком случае обращаться к этой переменной в
catch-обработчиках нельзя:
int main() {
try {
iStack stack( 32 ); // правильно: объявление внутри try-блока
stack.display();
for ( int ix = 1; ix
Можно объявить функцию так, что все ее тело
будет заключено в try-блок. При этом не обязательно
помещать try-блок внутрь определения функции, удобнее
поддерживает наиболее чистое разделение кода для нормальной обработки
и кода для обработки исключений. Например:
int main()
try {
iStack stack( 32 ); // правильно: объявление внутри try-блока
stack.display();
for ( int ix = 1; ix 51; ++ix )
{
// то же, что и раньше
}
return 0;
}
catch ( pushOnFull ) {
// здесь к переменной stack обращаться нельзя
}
catch ( popOnEmpty ) {
// здесь к переменной stack обращаться нельзя
}
Обратите внимание, что ключевое слово try находится перед фигурной скобкой, открывающей тело функции, а catch-обработчики перечислены после закрывающей его скобки. Как видим, код, осуществляющий нормальную обработку, находится внутри тела функции и четко отделен от кода для обработки исключений. Однако к переменным, объявленным в main(), нельзя обратиться из обработчиков исключений.
Функциональный try-блок ассоциирует группу catch-обработчиков с телом функции. Если инструкция возбуждает исключение, то поиск обработчика, способного перехватить это исключение, ведется среди тех, что идут за телом функции. Функциональные try-блоки особенно полезны в сочетании с конструкторами классов. (Мы еще вернемся к этой теме в главе 19.)
Упражнение 11.3
Напишите программу, которая определяет объект IntArray (тип класса IntArray рассматривался в разделеa 2.3) и выполняет описанные ниже действия.
Пусть есть три файла, содержащие целые числа.
* Прочитать первый файл и поместить в объект IntArray первое, третье, пятое, ..., n-ое значение (где n нечетно). Затем вывести содержимое объекта IntArray.
* Прочитать второй файл и поместить в объект IntArray пятое, десятое, ..., n-ое значение (где n кратно 5). Вывести содержимое объекта.
* Прочитать третий файл и поместить в объект IntArray второе, четвертое, ..., n-ое значение (где n четно). Вывести содержимое объекта.
Воспользуйтесь оператором operator[]() класса IntArray, определенным в упражнении 11.2, для сохранения и получения значений из объекта IntArray. Так как operator[]() может возбуждать исключения, обработайте их, поместив необходимое количество try-блоков и catch-обработчиков. Объясните, почему вы разместили try-блоки именно так, а не иначе.
11.3. Перехват исключений
В языке C++ исключения обрабатываются в предложениях catch. Когда какая-то инструкция внутри try-блока возбуждает исключение, то просматривается список последующих предложений catch в поисках такого, который может его обработать.
Catch-обработчик состоит из трех частей: ключевого слова catch, объявления одного типа или одного объекта, заключенного в круглые скобки (оно называется объявлением исключения), и составной инструкции. Если для обработки исключения выбрано некоторое catch-предложение, то выполняется эта составная инструкция. Рассмотрим catch-обработчики исключений pushOnFull и popOnEmpty в функции main() более подробно:
catch ( pushOnFull ) {
cerr "trying to push value on a full stack\n";
return errorCode88;
}
catch ( popOnEmpty ) {
cerr "trying to pop a value on an empty stack\n";
return errorCode89;
}
В обоих catch-обработчиках есть объявление типа класса; в первом это pushOnFull, а во втором – popOnEmpty. Для обработки исключения выбирается тот обработчик, для которого типы в объявлении исключения и в возбужденном исключении совпадают. (В главе 19 мы увидим, что типы не обязаны совпадать точно: обработчик для базового класса подходит и для исключений с производными классами.) Например, когда функция-член pop() класса iStack возбуждает исключение popOnEmpty, то управление попадает во второй обработчик. После вывода сообщения об ошибке в cerr, функция main() возвращает код errorCode89.