Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Возбуждение нескольких исключительных ситуацийСодержание книги
Поиск на нашем сайте
В функциях можно возбуждать объекты исключительных ситуаций различных типов для поддержки различных условий исключительных ситуаций. Вот гипотетический пример, в котором обеспечивается поддержка исключительных ситуаций двух видов: int AnyFunctionO if (conditionA) throw "Big trouble!"; if (conditionB) throw OverflowO; return 123; Если условие conditionA справедливо (что бы оно ни значило), функция возбуждает строковую исключительную ситуацию с сообщением "Big trouble!". Если выполняется условие conditionB, функция посылает объект класса Overflow, создаваемый в данном случае с помощью обращения к конструктору класса по умолчанию. Если же функция не обнаружила ошибок, она возвращается обычным образом, передавая значение 123 тому, кто ее вызвал. Вот три важных следствия из приведенного примера. • Функции могут возбуждать одну или несколько исключительных ситуаций различных типов, представляющих различные условия исключительных ситуаций. • Возбуждение исключительной ситуации немедленно завершает выполнение функции, в которой выполняется оператор throw.» • Как подсказывают два предыдущих наблюдения, исключительные ситуации обеспечивают альтернативный механизм возврата для функций. Последнее замечание — ключевое. Функция AnyFunctionO обычно возвращает целочисленное значение, однако, если возникает исключительная ситуация она возвращает строку или объект класса Overflow. Только операторы catch могут воспринять эти возвращаемые значения. Если исключительных ситуаций не возникло, функция завершается нормально, возвращая (необязательно) значение типа, с которым объявляется функция, обратно оператору вызова этой функции. Вы можете поддерживать несколько типов объектов исключительных ситуаций с помощью серии операторов catch. Например, для обработки исключительных ситуаций для класса Error и строк напишите следующие операторы catch один за другим: catch (Error e) { // Обработка исключительной ситуации для класса Error } catch (const char* message) < // Обработка исключительной ситуации для строк } Введение в блоки try Теперь настало время для изучения еще одной премудрости — блоков try, которые, кажется, смущают любого, кто только начал ими пользоваться. Для того чтобы принимать объекты исключительных ситуаций некоторой функции, вызовите ее внутри блока try: try { int x = AnyFunctionO; > catch (Error e) { e.ReportO;) Блок try содержит один или несколько операторов, исключительные ситуации которых вы хотите перехватывать. Один или более операторов catch должны следовать за блоком try. Это похоже на ситуацию, когда игрок разбегается, чтобы пробить пенальти, а вратарь готовится отразить удар. В любом случае, после блока try следует поместить один или несколько операторов catch, перехватывающих все исключительные ситуации, возбуждаемые этими операторами. Несколько блоков try и соответствующих им операторов catch могут быть объявлены вложенными, хотя синтаксис в этом случае может привести к запутанному коду. Например, блок try может иметь вложенные блок try и операторы catch в следующем гипотетическом примере, причем, если в функции FunctionAO возбуждается исключительная ситуация, программа полностью пропускает вложенный блок try: try { FunctionAO; try { FunctionBO; catch (Error e) { e.ReportO; // ReportO catch (Error e) { e.ReportO;} Использование блоков try Несколько дополнительных примеров помогут выяснить, что представляют собой блоки try и как ими пользоваться. В блоке try может быть несколько операторов (обычно так и бывает): try { cout «"Here we go!" << endl; int x = AnyFunctionO; cout «"x == " «x «endl; j В блоке try сначала отображается сообщение. Затем в нем вызывается функция AnyFunctionO, результат которой присваивается целочисленной переменной х. Если в функции AnyFunction возникла исключительная ситуация, блок try немедленно завершается. Другими словами, любое условие исключительной ситуации приводит к пропуску присваивания х и завершающего оператора вывода. ЗАМЕЧАНИЕ Особенно важен тот факт, что при возбуждении исключительной ситуации функцией AnyFunctionO в предыдущем фрагменте кода, присваивания значения целочисленной переменной х не произойдет. За блоком try должны следовать один или несколько операторов catch (иначе не имеет смысла использовать try). Вот более законченный пример того, как можно обработать несколько исключительных ситуаций, которые может возбудить функция, подобная AnyFunctionO: try { cout «"Here we go!" «endl; int x = AnyFunctionO; cout «"x.== " «x << endl; } ■ catch (char* message) { cout << "Error! -- " << message «endl; exit(-1); // Необязательно } catch (Overflow) { cout «"Overflow!" «endl; exit(-2); // Необязательно } // В этом месте программа продолжает выполнение как обычно В этом более пространном коде сначала испытывается вызов функции AnyFunctionO. Если функция завершилась нормально, ее результат присваивается переменной х, которая отображается в следующем операторе записи в стандартный поток вывода. Если исключительных ситуаций не было, оба оператора catch пропускаются, поскольку нет объектов исключительных ситуаций объявленных типов, которые нужно было бы перехватывать. Конечно, если функция AnyFunctionO возбуждает исключительную ситуацию, выполнение блока try немедленно прерывается, посланные объекты перехватываются соответствующими операторами catch, a именно тем из них, в котором объявлен параметр типа, соответствующего типу данных посланного объекта. В данном примере в операторах catch вызывается библиотечная функция exitO для аварийного завершения программы. Приведенная реакция не обязательна — вам предоставляется самому решать, что делать в ответ на возбуждение исключительной ситуации. Вы можете вставить один, два, три или более операторов catch после блока try для обработки исключительных ситуаций различных типов. В этом примере два оператора catch обрабатывают исключительные ситуации для строк и класса Overflow. Любые другие типы исключительных ситуаций, не обрабатываемые операторами catch, передаются вверх по цепочке вызовов. Например, предположим, что функция AnyFunction также возбуждает исключительную ситуацию типа NewException. Если в функции g() был вызван упомянутый выше код, объект этой исключительной ситуации будет передаваться наверх в g(), так как в этом коде обрабатываются только исключительные ситуации типов char* и Overflow. В конце концов, если ни один оператор catch подходящего типа не был найден в цепочке вызовов, ведущих к исключительной ситуации, выполнение программы прерывается вызовом специального обработчика исполняющей системы. Чтобы этого не произошло, следует запрограммировать все операторы catch для всех возможных типов посылаемых объектов. ЗАМЕЧАНИЕ Исключительные ситуации упраздняют необходимость резервирования специальных возвращаемый значений для ошибок. Например, в классическом программировании на С и C++ для функции, возвращающей целое значение, может указываться, что сигнализирует об ошибке, прочие же возвращаемые значения — допустимые. В этом приеме нет ничего неправильного, просто резервирование специальных значений не всегда возможно. Рассмотрим функцию, суммирующую список целых значений. В этом случае все возвращаемые значения могут быть допустимыми, и невозможно зарезервировать одно из них для особого случая. Большинство программистов решают эту проблему, определяя глобальную переменную-флаг для ошибок, которая должна проверяться в программе обнаружения ошибок после вызова функции. Исключительные ситуации позволяют отказаться от такого запутанного способа обработки ошибок с помощью возврата объектов, представляющих состояния исключительных ситуаций без конфликтов с нормальными возвращаемыми значениями функции. Программирование с исключительными ситуациями Пример программы EXCEPT.CPP (листинг 15.16) демонстрирует использование исключительных ситуаций ANSI C++. Вы можете скомпилировать и запустить программу из DOS или WINDOWS. Из приглашения DOS следует ввести bec except, а затем имя программы для запуска получившегося в результате исполняемого файла EXCEPT.EXE. Или же из интегрированной среды скомпилируйте и запустите программу в качестве Easy Win-приложения. ЗАМЕЧАНИЕ Для демонстрации в модуле EXCEPT.CPP имеется оператор, который не выполняет никаких действий, что служит причиной предупреждений компилятора "Unread/able, code at line 78" (Недостижимый код и строке 78). Я включил этот оператор throw для отладки. Если вы сделаете ошибку, модифицировав программу (конечно, она хранится на диске, и вы не должны этого делать), оператор throw в строке 78 создаст объект класса Error с помощью вызова конструктора по умолчанию. Изучите объявление класса. Созданный таким способом, объект Error отобразит сообщение, свидетельствующее об ошибке в исходном коде. Листинг 15.16. EXCEPT.CPP (использование исключительных ситуаций ANSI C++) // Демонстрация исключительных ситуаций ANSI C++ «include <iostream.h> «include <math.h> // Прототипы функций void Instruct(); double Pow(double b, double e); double Power(double b, double e); // Классы исключительных ситуаций class Error { double b; // Основание double e; // Показатель степени public: ErrorQ { cout «"Error in source codei" «endl; } Error(double bb, double ее): b(bb), e(ee) { } void ReportO;
int main() Instruct(); try { double base, exponent, result; cout << "base? "; cin» base; cout «"exponent? "; cin >> exponent; result = Power(base, exponent); cout << "result == " «result << endl; catch (Error& e) { return 0; void Instruct() cout «"Power Demonstration\n\n"; cout «"This program displays the result of raising\n"; cout «"a value (base) to a power (exponent). To\n"; cout << "force an exception, enter a negative base\n"; cout << "and a fractional exponent (e.g. -4 and 1.5)\n"; cout << "Or, enter a zero base and an exponent less than\n"; cout << "zero.\n\n"; // Подфункция возведения в степень double Pow(double b, double e) { return exp(e * log(b)); > // Результирующий b возведенный в степень е double Power(double b, double e) < if (b > 0.0) return Pow(b, e); if (b < 0.0) { double ipart; double fpart = modf(e, &ipart); if (fpart == 0) { if (fmod(ipart, 2)!= 0) // Таким образом, ipart - нечетное число return -Pow(-b, e); else return Pow(-b, e); } else throw Error(b, e); } else { if (e == 0.0) return 1.0; if (e < 1.0) throw Error(b, e); return 0.0; } throw ErrorO; // В этом месте будет предупреждение } // Отображение значений, вызвавших исключительную ситуацию void
Error::Report() { cout «"Domain error:" «" base:" «b << " exponent:" << e «endl; } В EXCEPT реализуется функция PowerO, способная возвести любое действительное число в любую действительную степень. Конечно, два условия исключительной ситуации заставляют функцию возбуждать исключительную ситуацию. • Возведение отрицательного числа в дробную степень. • Возведение нуля в отрицательную степень. Для обработки подобных ситуаций наилучшим образом подходят исключительные ситуации. Имеются та! же следующие альтернативы — прервать выполнение программы (плохо), возвратить специальное значение (не подходит) или установить глобальный флаг ошибки (плохой стиль программирования). Вместо применения этих относительно неудачных решений, функция Power возбуждает исключите льну] ситуацию, представленную объектом класса Error. Например, при попытке возвести отрицательное число дробную степень функция Power выполняет следующий оператор, создающий объект класса Error, инициализированный значениями b и е: throw Error(b, e); Вернемся к функции main(). Функция Power вызывается внутри блока try, часть которого приведем еще раз try { double ba.se, exponent, result //... запрашиваются основание и показатель степени result = Power(base, exponent); cout «"result == " << result «endl; Если функция Power возбуждает исключительную ситуацию, присваивание переменной result и следующий оператор вывода пропускаются, а блок try немедленно завершается. Оператор catch следует сразу же за блоком try: catch (Error& e) { e.Report(); return -1; } return 0;
Если функция Power возбуждает исключительную ситуацию, объект е класса Error перехватывается по ссылке. В операторе catch вызывается функция-член Report класса Error для объекта исключительной ситуации е, отображающая значения, приведшие к ненормальному завершению функции Power. ЗАМЕЧАНИЕ Хотя вы можете посылать и перехватывать объекты по значению, использование ссылок, коды посылаются объекты классов, обычно дает лучшие результаты, поскольку экономится пространство стека. Этот прием также упрощает используемые классы, так как отпадает необходимость в конструкторах копии, особенно, если они к тому же выделяют память. Итак, программа осуществляет полный контроль над исключительными ситуациями. Пример заканчивает работу с кодом завершения, если были ошибки, или 0, если ошибок не было. Это обычная практика для программ, хотя операционные системы DOS и Windows игнорируют возвращаемые программами значения. Бывают случаи, когда завершение программы нежелательно и возникает необходимость повторить операторы, приведшие к исключительной ситуации, — в данном случае, указав для new новые значения. Далее в этой главе я объясню, как использовать исключительные ситуации в этом случае, но сначала вы должны узнать об альтернативных формах объявления функций, возбуждающих исключительные ситуации.
|
|||||
Последнее изменение этой страницы: 2016-08-01; просмотров: 207; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.133.133.251 (0.009 с.) |