Г. Шилтд - Самоучитель C++ (PDF) (1114887), страница 50
Текст из файла (страница 50)
Это могут быть как несколько инструкций внутри одной функции, так и все инструкции внутри функции inainO (что естественно ведет к отслеживанию ошибок во всей программе).После того как исключительная ситуация возбуждена, она перехватываетсясоответствующей этой конкретной исключительной ситуации инструкциейcatch, которая ее обрабатывает. С блоком try может быть связано более одной инструкции catch. To, какая именно инструкция catch используется,зависит от типа исключительной ситуации. То есть, если тип данных, указанный в инструкции catch, соответствует типу исключительной ситуации,выполняется данная инструкция catch. При этом все оставшиеся инструкции блока try игнорируются (т. е. сразу после того, как какая-то инструкцияв блоке try вызвала появление исключительной ситуации, управление передается соответствующей инструкции catch, минуя оставшиеся инструкцииблока try, — примеч.
пер.). Если исключительная ситуация перехвачена, аргумент arg получает ее значение. Если вам не нужен доступ ксамой исключительной ситуации, можно в инструкции catch указать толькоее тип type, аргумент arg указывать не обязательно. Можно перехватыватьГлава 11. Шаблоны и обработка исключительных ситуаций339любые типы данных, включая и типы создаваемых вами классов. Фактически в качестве исключительных ситуаций часто используются именно типы классов.Далее представлена основная форма инструкции throw:throw исклю«ительная_си!гуация;Инструкция throw должна выполняться либо внутри блока try, либо в любойфункции, которую этот блок вызывает (прямо или косвенно).
Здесьисключмпельная^ситпуация — это возбуждаемая инструкцией throw исключительная ситуация.Если вы возбуждаете исключительную ситуацию, для которой нет соответствующей инструкции catch, может произойти ненормальное завершение программы. Если ваш компилятор функционирует в соответствии со стандартомStandard C++, то возбуждение необрабатываемой исключительной ситуацииприводит к вызову стандартной библиотечной функции terminate(). По умолчанию для завершения программы функция terminate() вызывает функциюabort(), однако при желании можно задать собственную процедуру завершения программы.
За подробностями обращайтесь к справочной документациивашего компилятора.1. В следующем очень простом примере показано, как в C++ функционируетсистема обработки исключительных ситуаций:// Простой пример обработки исключительной ситуацииttinclude <iostream>using namespace std;int mainOcout « "начало \n";try {// начало блока trycout « "Внутри блока try\n";throw 10;// возбуждение ошибкиcout « "Эта инструкция выполнена не будет"}catch (int i) { // перехват ошибкиcout « "перехвачена ошибка номер: ";cout « i « "\n";cout « "конец";return 0;340_СамоучительC++После выполнения программы на экран будет выведено следующее:началоВнутри блока tryПерехвачена ошибка номер: 10конецВнимательно изучите программу. Как видите, здесь имеется блок try, содержащий три инструкции, и инструкция catch (int i), обрабатывающая исключительную ситуацию целого типа.
Внутри блока try будут выполнены толькодве из трех инструкций — инструкции cout и throw. После того как исключительная ситуация возбуждена, управление передается выражению catch ивыполнение блока try завершается. Таким образом, инструкция catch вызывается не явно, управление выполнением программы просто передается этойинструкции.
(Для этого стек автоматически сбрасывается.) Следовательно,следующая за инструкцией throw инструкция cout не будет выполнена никогда.После выполнения инструкции catch, управление программы передается следующей за ней инструкции. Тем не менее, обычно блок catch заканчивают вызовом функции exit(), abort() или какой-либо другой функции, принудительно завершающей программу, поскольку, как правило, система обработки исключительных ситуаций предназначена для обработки катастрофических ошибок.2. Как уже упоминалось, тип исключительной ситуации должен соответствоватьтипу, заданному в инструкции catch.
Например, в предыдущем примере, еслиизменить тип данных в инструкции catch на double, то исключительная ситуация не будет перехвачена и будет иметь место ненормальное завершениепрограммы. Это продемонстрировано в следующем фрагменте:// Этот пример работать не будет^include <iostream>using namespace std;int main ( ){cout « "начало\п";try {// начало блока trycout « "Внутри блока try\n";throw 10;// возбуждение ошибкиcout « "Эта инструкция выполнена не будет";}catch (double i) { // Эта инструкция не будет работать// с исключительной ситуацией целого типаcout « "перехвачена ошибка номер: ";cout « i « "\n";cout « "конец";return 0;Глава 11. Шаблоны и обработка исключительных ситуаций341Поскольку исключительная ситуация целого типа не будет перехвачена инструкцией catch типа double, на экран программа выведет следующее:началоВнутри блока tryAbnormal program termination3.
Исключительная ситуация может быть возбуждена не входящей в блок tryинструкцией, если сама эта инструкция входит в функцию, которая вызывается из блока try- Например, ниже представлена совершенно правильнаяпрограмма:/* Возбуждение исключительной ситуации из функции, находящейся внеблока try*/ttinclude <iostream>using namespace std;void Xtest(int test)tcout « "Внутри функции Xtest, test равно: " « test « "\n";if (test) throw test;int main()Icout « "начало\п";try {// начало блока trycout « "Внутри блока try\n";Xtest (0);Xtest (1);Xtest (2);catch (int i) { // перехват ошибкиcout « "перехвачена ошибка номер: ";cout « i « "\n";cout « "конец";return 0;1На экран программа выводит следующее:началоВнутри блока tryВнутри функции Xtest, test равно: ОВнутри функции Xtest, test равно: 1__342Самоучитель C++Перехвачена ошибка номер: 1конец4.
Блок try можно располагать внутри функции. В этом случае при каждом входе в функцию обработчик исключительной ситуации устанавливается снова.Например, рассмотрим следующую программу:^include <iostream>using namespace std;// Блоки try и catch могут находиться не только в функции main ( )void Xhandler (int test)(try fif (test) throw test;}catch(int i) {cout « "перехвачена ошибка номер : " « i « ' \n ' ;int main ( }{cout « "началоХп";Xhandler (1) ;Xhandler (2} ;Xhandler (0) ;Xhandler (3) ;cout « "конец";return 0;На экран программа выводит следующее:началоПерехвачена ошибка номер: 1Перехвачена ошибка номер: 2Перехвачена ошибка номер: 3конецКак видите, обработаны три исключительные ситуации.
После вызова каждой исключительной ситуации функция возвращает свое значение. При повторном вызове функции обработчик исключительной ситуации устанавливается вновь.5. Как упоминалось ранее, с блоком try можно связать более одной инструкцииcatch. Как правило, так и делается. При этом каждая инструкция catch пред-Глава 11. Шаблоны и обработка исключительных ситуаций343назначена для перехвата своего типа исключительной ситуации. Например, вследующей программе перехватываются две исключительных ситуации, однадля целых и одна для строки:tinclude <iostream>using namespace std;•// Можно перехватывать разные типы исключительных ситуацийvoid Xhandler(int test}try{i f ( t e s t ) throw test;else throw "Значение равно нулю";.catch (int i} {cout « "Перехвачена ошибка номер: " « i « '\n';catch(char *str) (cout « "Перехвачена строка: ";cout « str « p \ n ' ;int main (){cout « "начало\п";Xhandler(l);Xhandler(2);Xhandler(O);Xhandler(3);cout « "конец";return 0;На экран программа выводит следующее:началоПерехваченаПерехваченаПерехваченаПерехваченаконецошибка номер: 1ошибка номер: 2строка: Значение равно нулюошибка номер: 3Как видите, каждая инструкция catch перехватывает только исключительныеситуации соответствующего ей типа.Обычно выражения инструкций catch проверяются в том порядке, в которомони появляются в программе.
Выполняется только та инструкция, которая344Самоучитель C++совпадает по типу данных с исключительной ситуацией. Все остальные блоки catch игнорируются.[Упражненияения]1. Лучший способ понять, как функционирует система обработки исключительных ситуаций в C++ — это поработать с ней. Введите, откомпилируйте изапустите предыдущие примеры программ. Затем поэкспериментируйте сними, меняя фрагменты и исследуя результаты.2. Что неправильно в данном фрагменте?int main (){throw 12.23;3.
Что неправильно в данном фрагменте?try{// . ..throw ' а ' ;catch (char *) {4. Что может произойти при возбуждении исключительной ситуации, для которой не задано соответствующей инструкции catch?11.4. Дополнительная информацияоб обработке исключительных ситуацийВ системе обработки исключительных ситуаций имеется несколько дополнительных аспектов и нюансов, которые могут сделать ее понятнее и удобней для применения.В некоторых случаях необходимо настроить систему так, чтобы перехватывать все исключительные ситуации, независимо от их типа.
Сделать это достаточно просто. Для этого используйте следующую форму инструкции catch:catch (...) {// обработка всех исключияелышх ситуацийГлава11.Шаблоныиобработкаисключительныхситуаций_345Здесь многоточие соответствует любому типу данных.Для функции, вызываемой из блока try, вы можете ограничить число типовисключительных ситуаций, которые способна возбудить такая функция.Фактически можно даже запретить функции вообще возбуждать какую быто ни было исключительную ситуацию.
Для этого необходимо добавить вопределение функции ключевое слово throw. Здесь представлена основнаяформа такого определения:возвраща&мый_тип имя_функции (список_аргумекч>ов)throw ( списох_ типов)IЗдесь в поле список_типов перечисляются через запятые только те типыданных исключительных ситуаций, которые могут быть возбуждены функцией. Возбуждение любого другого типа исключительной ситуации приведетк аварийному завершению программы. Если вы хотите, чтобы функция невозбуждала никаких исключительных ситуаций, то оставьте поле список_типов пустым.Если ваш компилятор работает в соответствии с современным стандартомStandard C++, то попытка возбуждения неподдерживаемой исключительнойситуации приведет к вызову стандартной библиотечной функции unexpected().По умолчанию функция unexpectedQ вызывает функцию abort(), что ведет каварийному завершению программы. Однако при желании вы можете задатьсобственную процедуру завершения программы. За подробностями обращайтесь к справочной документации вашего компилятора.Если вы хотите в процедуре обработки исключительной ситуации возбудить повторную исключительную ситуацию, можно просто использовать инструкциюthrow без параметров.