Какие из приведенных инструкций throw ошибочны? Почему? Для правильных инструкций укажите тип возбужденного исключения:
(a) class exceptionType { };
throw exceptionType();
(b) int excpObj;
throw excpObj;
(c) enum mathErr { overflow, underflow, zeroDivide };
throw mathErr zeroDivide();
(d) int *pi = excpObj;
throw pi;
Упражнение 11.2
У класса IntArray, определенного в разделе 2.3, имеется функция-оператор operator[](), в которой используется assert() для извещения о том, что индекс вышел за пределы массива. Измените определение этого оператора так, чтобы в подобной ситуации он генерировал исключение. Определите класс, который будет употребляться как тип возбужденного исключения.
11.2. Try-блок
В нашей программе тестируется определенный в предыдущем разделе класс iStack и его функции-члены pop() и push(). Выполняется 50 итераций цикла for. На каждой итерации в стек помещается значение, кратное 3: 3, 6, 9 и т.д. Если значение кратно 4 (4, 8, 12...), то выводится текущее содержимое стека, а если кратно 10 (10, 20, 30...), то с вершины снимается один элемент, после чего содержимое стека выводится снова. Как нужно изменить функцию main(), чтобы она обрабатывала исключения, возбуждаемые функциями-членами класса iStack?
#include
#include "iStack.h"
int main() {
iStack stack( 32 );
stack.display();
for ( int ix = 1; ix 51; ++ix )
{
if ( ix % 3 == 0 )
stack.push( ix );
if ( ix % 4 == 0 )
stack.display();
if ( ix % 10 == 0 ) {
int dummy;
stack.pop( dummy );
stack.display();
}
}
return 0;
}
Инструкции, которые могут возбуждать исключения, должны быть заключены в try-блок. Такой блок начинается с ключевого слова try, за которым идет последовательность инструкций, заключенная в фигурные скобки, а после этого – список обработчиков, называемых catch-предложениями. Try-блок группирует инструкции программы и ассоциирует с ними обработчики исключений. Куда нужно поместить try-блоки в функции main(), чтобы были обработаны исключения popOnEmpty и pushOnFull?
for ( int ix = 1; ix 51; ++ix ) {
try { // try-блок для исключений pushOnFull
if ( ix % 3 == 0 )
stack.push( ix );
}
catch ( pusOnFull ) { ... }
if ( ix % 4 == 0 )
stack.display();
try { // try-блок для исключений popOnEmpty
if ( ix % 10 == 0 ) {
int dummy;
stack.pop( dummy );
stack.display();
}
}
catch ( popOnEmpty ) { ... }
}
В таком виде программа выполняется корректно. Однако обработка исключений в ней перемежается с кодом, использующимся при нормальных обстоятельствах, а такая организация несовершенна. В конце концов, исключения – это аномальные ситуации, возникающие только в особых случаях. Желательно отделить код для обработки аномалий от кода, реализующего операции со стеком. Мы полагаем, что показанная ниже схема облегчает чтение и сопровождение программы:
try {
for ( int ix = 1; ix
С try-блоком ассоциированы два catch-предложения, которые
могут обработать исключения pushOnFull и popOnEmpty, возбуждаемые
функциями-членами push() и pop() внутри этого блока. Каждый catch-обработчик
определяет тип "своего" исключения. Код для обработки исключения помещается
внутрь составной инструкции (между фигурными скобками), которая является частью
catch-обработчика. (Подробнее catch-предложения мы рассмотрим в следующем разделе.)
Исполнение программы может пойти по одному из следующих путей:
если исключение не возбуждено, то выполняется код внутри try-блока, а ассоциированные
* с ним обработчики игнорируются. Функция main() возвращает 0;
если функция-член push(), вызванная из первой инструкции if внутри цикла for,
возбуждает исключение, то вторая и третья инструкции if игнорируются,
управление покидает цикл for и try-блок, и выполняется обработчик исключений
* типа pushOnFull;
если функция-член pop(), вызванная из третьей инструкции if внутри
цикла for, возбуждает исключение, то вызов display() игнорируется,
управление покидает цикл for и try-блок, и выполняется обработчик исключений
* типа popOnEmpty.
Когда возбуждается исключение, пропускаются все инструкции,
следующие за той, где оно было возбуждено. Исполнение программы
возобновляется в catch-обработчике этого исключения. Если такого