|
Программирование >> Инициализация объектов класса, структура
#include <iostream> #include iStack.h int main() { iStack stack 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, за которым идет последовательность инструкций, заключенная в фигурные скобки, а после этого - список обработчиков, называем1х catch-предложениями. Try-блок группирует инструкции программа: и ассоциирует с ними обработчики исключений. Куда нужно поместить try-блоки в for ( int ix = 1; ix < 51; ++ix ) { try { try-блок для искчений pushCnFull if ( ix % 3 == 0 ) stack.push( ix ); catch ( pusCnFull ) { ... } if ( ix % 4 == 0 ) stack.display(); try { try-блок для искчений popCnEmpty if ( ix % 10 == 0 ) { int dummy; stack.pop( dummy ); stack.display(); catch ( popCnEmpty ) { ... } функции main() , чтобы были обработаны исключения popCnEmpty и pushCnFull? В таком виде программа выполняется корректно. Однако обработка исключений в ней перемежается с кодом, использующимся при нормальных обстоятельствах, а такая организация несовершенна. В конце концов, исключения - это аномальные ситуации, возникающие только в особых случаях. Желательно отделить код для обработки try { 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(); catch ( pushCnFull ) { ... } схема облегчает чтение и сопровождение программы: catch ( popCnEmpty ) { ... } С try-блоком ассоциирован! два catch-нредложения, которые могут обработать исключения pushCnFull и popCnEmipty, возбуждаем1е функциями-членами push() и pop() внутри этого блока. Кажд1й catch-обработчик определяет тин своего исключения. Код для обработки исключения помещается внутрь составной инструкции (между фигурными скобками), которая является частью catch-обработчика. (Подробнее catch-нредложения м1 рассмотрим в следующем разделе.) Исполнение программы может пойти по одному из следующих путей: если исключение не возбуждено, то выполняется код внутри try-блока, а ассоциированные с ним обработчики игнорируются. Функция miain() возвращает 0; если функция-член push() , вызванная из первой инструкции if внутри цикла for, возбуждает исключение, то вторая и третья инструкции if игнорируются, управление покидает цикл for и try-блок, и выполняется обработчик исключений типа pushCnFull; если функция-член pop() , вызванная из третьей инструкции if внутри цикла for, возбуждает исключение, то вызов display() игнорируется, управление покидает цикл for и try-блок, и выполняется обработчик исключений тина popCnEmipty. Когда возбуждается исключение, пропускаются все инструкции, следующие за той, где оно было возбуждено. Исполнение программа: возобновляется в catch-обработчике этого исключения. Если такого обработчика не существует, то управление передается в функцию terminate() , определенную в стандартной библиотеке C++. Try-блок может содержать любую инструкцию яз1ка C++: как выражения, так и объявления. Он вводит локальную область видимости, так что объявленные внутри него неременные недоступны вне этого блока, в том числе и в catch-обработчиках. Например, функцию main() можно переписать так, что объявление переменной stack окажется в try-блоке. В таком случае обращаться к этой неременной в catch-обработчиках нельзя: аномалий от кода, реализующего операции со стеком. Мы полагаем, что показанная ниже int main() { try { iStack stack( 32 ); правильно: объявление внутри try-блока stack.display(); for ( int ix = 1; ix < 51; ++ix ) { то же, что и раньше catch ( pushCnFull ) { здесь к переменной stack обращаться нельзя catch ( popCnEmpty ) { здесь к переменной stack обращаться нельзя и здесь к переменной stack обращаться нельзя return 0; Можно объявить функцию так, что все ее тело будет заключено в try-блок. При этом не обязательно помещать try-блок внутрь определения функции, удобнее заключить ее тело в функциональный try-блок. Такая организация поддерживает наиболее чистое разделение int main() try { iStack stack( 32 ); правильно: объявление внутри try-блока stack.display(); for ( int ix = 1; ix < 51; ++ix ) { то же, что и раньше return 0; catch ( pushCnFull ) { здесь к переменной stack обращаться нельзя catch ( popCnEmpty ) { здесь к переменной stack обращаться нельзя кода для нормальной обработки и кода для обработки исключений. Например: Обратите внимание, что ключевое слово try находится перед фигурной скобкой, открывающей тело функции, а catch-обработчики перечислена: после закрывающей его скобки. Как видим, код, осуществляющий нормальную обработку, находится внутри тела функции и четко отделен от кода для обработки исключений. Однако к переменным, объявленным в main() , нельзя обратиться из обработчиков исключений. Функциональный try-блок ассоциирует группу catch-обработчиков с телом функции. Если инструкция возбуждает исключение, то поиск обработчика, способного перехватить это исключение, ведется среди тех, что идут за телом функции. Функциональные try-блоки особенно полезны в сочетании с конструкторами классов. (Мы еще вернемся к этой теме в главе 19.)
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |