Главная Случайная страница


Полезное:

Как сделать разговор полезным и приятным Как сделать объемную звезду своими руками Как сделать то, что делать не хочется? Как сделать погремушку Как сделать неотразимый комплимент Как противостоять манипуляциям мужчин? Как сделать так чтобы женщины сами знакомились с вами Как сделать идею коммерческой Как сделать хорошую растяжку ног? Как сделать наш разум здоровым? Как сделать, чтобы люди обманывали меньше Вопрос 4. Как сделать так, чтобы вас уважали и ценили? Как сделать лучше себе и другим людям Как сделать свидание интересным?

Категории:

АрхитектураАстрономияБиологияГеографияГеологияИнформатикаИскусствоИсторияКулинарияКультураМаркетингМатематикаМедицинаМенеджментОхрана трудаПравоПроизводствоПсихологияРелигияСоциологияСпортТехникаФизикаФилософияХимияЭкологияЭкономикаЭлектроника






Исключения





Для обработки нештатных ситуаций в язык C++ внесены следующие служебные слова – try (попробуй, проверь), catch(перехвати) и throw (имитируй событие). В версии BC 3.1 эти средства еще не были задействованы, поэтому содержимое настоящего раздела распространяется на среду Borland C++ Builder.

Программный блок, в котором могут возникнуть нештатные события, заключается в фигурные скобки, перед которыми располагается служебное слово try:

try { контролируемый участок программы }

Если на контролируемом участке программы возникает та или иная особая ситуация, то для ее анализа надо предусмотреть одну или несколько ловушек, каждая из которых начинается со служебного слова catch:

catch(тип_события_1 значение_события_1) { блок обработки события_1 }

catch(тип_события_2 значение_события_2) { блок обработки события_2 }

.........................................................

Аргумент оператора catch можно рассматривать как специфический объект некоторого класса. Этот объект может быть создан как в результате аварийной ситуации, фиксируемой операционной системой, так и в результате выполнения программой оператора throw. Вторая возможность позволяет программе пользователя генерировать особые ситуации в случае выполнения условий, запланированных в работе алгоритма, и структурировать обработку возникающих событий в блоках catch.

Рассмотрим в качестве примера защищенную функцию fact(n), вычисляющую n!, которая возвращает значение типа double.По определению аргумент функции факториал не может быть отрицательным, а из диапазона представления вещественных данных типа double следует, что аргумент n не должен превосходить величины 1754, т.к. 1755! > 1e+308. Конечно, проверки аргумента на принадлежность допустимому интервалу можно было предусмотреть в теле функции, например, следующим образом:

double fact(int n)

{ if(0>n || n>1754)

{ cerr<<"fact: недопустимый аргумент"<<endl;

getch(); exit(1)

}

if(n==0)return 1;

else return n*fact(n-1);



}

Однако такая жесткая реакция на недопустимый аргумент всегда приведет к завершению работы приложения. А вдруг в распоряжении пользователя имеется возможность изменить схему алгоритма, и в ответ на возникшую ситуацию он захочет предпринять какие-то другие действия. Бoльшую гибкость в подобной ситуации может обеспечить следующая схема:

double fact(int n)

{ try

{ if(n<0) throw "fact: Argument < 0";

if(n>1754) throw "fact: Argument too big";

if(n==0)return 1;

else return n*fact(n-1);

}

catch(const char *s)

{ cerr<<s<<endl; //вывод сообщения об ошибке

return -1; //возврат несуществующего значения функции

}

}

В приведенном примере в случае выхода аргумента за пределы области определения срабатывает один из операторов throw, который генерирует объект типа символьная строка и прерывает работу контролируемого блока try (напоминает выход изцикла по оператору break ). Ловушка catch настроена на перехват исключений типа символьная строка, об этом свидетельствует тип ее аргумента. В процессе обработки возникшего события блок catch выводит полученное сообщение и возвращает несуществующее значение функции. По такому результату вызывающая программа может сообразить, что необходимо предпринять для продолжения работы. Если аргумент функции fact оказался допустимым, то после удачного выполнения блока try фрагмент программы-ловушки обходится.

Следует заметить, что механизм обработки исключений еще не попал в стандарт языка C++, поэтому разные системы программирования проводят обработку таких событий по-разному. Система BCB, обнаружив оператор throw, сначала выдает общее предупреждение о происшедшем событии:

Project ... raised exception class char * with message 'Exception Object Address: ...'

Process Stopped. Use Step or Run to continue.

После этого нажатие клавиши F9 (команда Run ) или F8 (команда Step ) передает управление блоку catch, который выдает сообщение, сгенерированное соответствующим оператором throw. В автоматическом режиме функция fact выдаст несуществующее значение факториала и программа продолжит свою работу:

void main()

{ int x=-5;

double z=fact(x);

cout<<"fact("<<x<<")="<<z<<endl;

getch();

}

//=== Результат работы ===

fact: Argument < 0

fact(-5)=-1

Система Visual C++ в такой ситуации не выдает системное предупреждение и не останавливает процесс – происходит просто автоматическая передача управления блоку catch.

В системе BCB существует довольно развитая иерархия классов, образованных от класса Exception. Например, один из таких порожденных классов EInvalidArgument, свидетельствующий об ошибке в аргументе, очень бы подошел в нашем примере:

double fact(int n)

{ try

{ if(n<0) throw EInvalidArgument("fact: Argument < 0");

if(n>1754) throw EInvalidArgument("fact: Argument too big");

if(n==0)return 1;



else return n*fact(n-1);

}

catch(EInvalidArgument &s)

{ cerr<<s.Message.c_str()<<endl; //вывод сообщения об ошибке

return -1; //возврат несуществующего значения функции

}

}

Для правильной работы такой функции нам понадобится подключение заголовочного файла math.hpp, в котором находится описание класса EInvalidArgument. В модифицированном варианте функции оператор throw использует конструктор этого класса для генерации ссылки на соответствующий объект. После обработки события в блоке catch созданный объект будет автоматически уничтожен. Обратите внимание на то, что все объекты класса Exception (и порожденных классов тоже) обладают свойством Message, значение которого представлено строкой типа AnsiString. Именно поэтому при выводе сообщения его приходится преобразовывать в обычную строку с помощью функции c_str.

Использование классов типа Exception существенно расширяет многообразие нестандартных ситуаций, которое может предусмотреть программа пользователя. Если бы для индикации событий мы использовали только переменные базовых типов, то количество различных ситуаций не превышало бы десятка ( char*, unsigned char*, short int, unsigned short int, ...).

Если в защищенном блоке может возникнуть несколько особых событий, которые связаны с разными объектами одного типа, то после блока try можно предусмотреть несколько обработчиков исключительных ситуаций. Последовательность их размещения может повлиять на правильность реакции на происшедшее событие. Дело в том, что сначала управление попробует получить блок catch, расположенный сразу после блока try. Если блок catch ориентирован на обработку однотипного события с другим значением, то при выходе из блока catch полученный объект-исключение будет уничтожен. И тогда следующий блокcatch, который мог бы справиться с возникшей ситуацией, уже не сработает. Поэтому первый блок catch, получив управление и обнаружив, что событие адресовано не ему, должен позаботиться о сохранении объекта для следующего обработчика. Для этого в конце первого блока catch должен находиться оператор throw().

В программах, связанных с обработкой исключений, можно встретить ловушку catch с аргументом в виде трех точек (catch(...) ). Такая ловушка перехватывает исключения любого типа.

2. Операции над числами в нормализованном виде

Давайте напоследок еще скажем, как суммировать, вычитать, умножать и делить в нормализованном виде.








Date: 2015-09-05; view: 70; Нарушение авторских прав

mydocx.ru - 2015-2018 year. (0.006 sec.) Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав - Пожаловаться на публикацию