Программирование >>  Инициализация объектов класса, структура 

1 ... 172 173 174 [ 175 ] 176 177 178 ... 395


#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.)



1 ... 172 173 174 [ 175 ] 176 177 178 ... 395

© 2006 - 2025 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки.
Яндекс.Метрика