Глава 10. Объектно-ориентированное программирование
case ’ - ’ :
v=a . pop ( ) ;
c o u t << "Извлечено число " << v << e n d l ;
break ;
case ’ i ’ :
c o u t << "Введите индекс: " ;
c i n >> i ;
v=a [ i ] ;
c o u t << "Искомый элемент равен " << v << e n d l ;
break ;
case ’ a ’ :
return 0 ;
break ;
}
}
catch ( const out_of_range& e )
{
c o u t << "Попытка доступа к элементу с недопустимым индексом "<< e . i << e n d l ;
}
catch ( o v e r f l o w )
{
c o u t << "Операция не выполнена, так как массив переполнен\ n " ;
}
catch ( u n d e r f l o w )
{
c o u t << "Операция не выполнена, так как массив пуст\ n " ;
}
}
}
В этом примере использованы четыре класса-индикатора исключений:
general_error
для ошибок неопределённого типа (класс содержит строку
message
, описывающую суть возникшей проблемы), out_of_range для выхода
индекса за границу массива (свойство i предусмотрено для значения индекса), а
также классы overflow для ошибки переполнения ёмкости массива и underflow
для попыток удалить элемент из пустого массива. Обработчик out_of_range
принимает объект класса-индикатора и сообщает пользователю, какое именно
значение индекса оказалось недопустимым. Диалог с пользователем ведётся в
бесконечном цикле, на каждой итерации которого предлагается выбрать одно из
четырёх действий: добавление элемента, удаление элемента, просмотр элемента
с заданным индексом или выход из программы.
10.5.3
Иерархия исключений
Классы-индикаторы исключения могут принадлежать к общей иерархии на-
следования, т. е. быть в отношениях «родитель-потомок». При этом обработ-
чики индикаторов-родительских классов могут перехватывать исключения с
индикаторами-потомками (можно считать такое поведение проявлением поли-
морфизма). Поэтому родительские обработчики нужно обязательно указывать
после
дочерних в цепочке блоков catch — иначе дочерний обработчик никогда
не получит управление. В самом конце цепочки можно указать catch, у которого
в круглых скобках вместо индикатора три точки. Такой блок будет перехваты-
вать абсолютно любые исключения:
c l a s s g e n e r a l _ e r r o r { } ;
Программирование на языке С++ в среде Qt Creator
10.5. Обработка исключений
311
c l a s s out_of_range : public g e n e r a l _ e r r o r { } ;
. . . . . . . . . . . . . .
try { . . . . . . . . . . . . . . . }
catch ( out_of_range )
{ c o u t << "Выход индекса за границу массива\ n " ; }
catch ( g e n e r a l _ e r r o r )
{ c o u t << "Общий сбой в работе программы\ n " ; }
catch ( . . . ) { c o u t << "Неизвестная ошибка\ n " ; }
В приведённом схематичном примере мы объявили два различных класса-
индикатора, один базовый, для исключений общего типа, и один производный от
него, для исключительной ситуации типа «недопустимый индекс при обращении
к в массиву». Если бы порядок следования обработчиков был другим, обработчик
индикатора out_of_range никогда не смог бы активироваться.
Если обработчик перехватил исключение, но обнаружил, что не сможет спра-
виться с его обработкой, он может вызвать throw без аргументов: это передаст
исключение дальше по цепочке уровней вложенности, на случай если на более
высоком уровне есть обработчик, способный так или иначе решить возникшую
ситуацию. Проиллюстрируем повторное возбуждение исключения, изменив при-
мер из п. 10.5.2. Цикл обработки событий мы поместим в отдельную функцию
main_loop()
, принимающую в качестве аргумента ссылку на массив. Соответ-
ственно, создание объекта массива и передачу его в цикл обработки событий
поместим в ещё один блок try, с обработчиком, принимающим исключение типа
general_error
. В первую очередь это позволит корректно обрабатывать ошиб-
ку нулевой ёмкости массива. Для иллюстрации передачи повторно сгенериро-
ванного исключения из внутреннего обработчика внешнему специально добавим
инструкцию throw без аргументов в обработчик события out_of_range (таким
образом, выход индекса за границу массива станет фатальной ошибкой, приводя-
щей к остановке программы). Чтобы исключение могло быть успешно перехваче-
но на внешнем уровне вложенности, сделаем класс general_error родительским
для остальных классов-индикаторов исключений.
#include
using namespace s t d ;
c l a s s g e n e r a l _ e r r o r
{
public :
char ∗ message ;
g e n e r a l _ e r r o r ( char∗ message ) { this −>message=message ; }
} ;
c l a s s out_of_range : public g e n e r a l _ e r r o r
{
public :
s i z e _ t i ;
out_of_range ( s i z e _ t i ) ;
} ;
out_of_range : : out_of_range ( s i z e _ t i )
: g e n e r a l _ e r r o r ( "Выход индекса за границу массива" )
{ this−>i=i ; }
c l a s s o v e r f l o w : public g e n e r a l _ e r r o r
{
public :
o v e r f l o w ( ) ;
} ;
o v e r f l o w : : o v e r f l o w ( ) : g e n e r a l _ e r r o r ( "Переполнение массива" ) {}
c l a s s u n d e r f l o w : public g e n e r a l _ e r r o r
© 2015 Алексеев Е. Р., Злобин Г. Г., Костюк Д. А., Чеснокова О. В., Чмыхало А. С.
312
Do'stlaringiz bilan baham: |