Студопедия

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

Разделы сайта

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






Stl исключения






В STL определено несколько классов исключений, которые используются различными компонентами библиотеки. Например, в файле stdexcept объявлены стандартные исключения:

· invalid_argument - вызывается при передаче неправильного аргумента;

· length_error - вызывается при превышении размера данных;

· out_of_range - вызывается при выходе за допустимые границы;

· overflow_error - вызывается при переполнении.

Эти и другие классы являются потомками класса exception. Через виртуальный метод what можно получить дополнительную информацию об исключении.

Обратите внимание, что в следующем примере исключение типа exception передается по ссылке, чтобы получить корректную строку описания ошибки. Это необязательно, если указывается конкретный класс, а не базовый.

#include < iostream> #include < stdexcept> using namespace std; class Range{int r1, r2, pos; public: Range(int rr1, int rr2, int ppos) {r1=rr1; r2=rr2; pos=ppos; } void setPos(int ppos){if(ppos< r1 ||ppos> r2) throw std:: invalid_argument(" setPos illegal argument! "); }}; int main() {Range r(10, 20, 12); try{ r.setPos(25); }catch(exception & e){ cout< < e.what(); }catch(...) { cout< < " unknown exception" < < endl; } return 0; }

 

ГЕНЕРАЦИЯ ИСКЛЮЧЕНИЙ

При обработке исключений используются всего четыре ключевых слова: try, catch, throw к finally. Способ применения ключевых слов прост и понятен. Когда метод не может выполнить свою задачу, т. е. когда он определяет исключительную ситуацию, то передает исключение вызывающему методу через ключевое слово throw. Вызывающий метод (если предположить, что он обладает достаточным контекстом для работы с исключением) получает это исключение посредством ключевого слова catch и решает, что предпринять. В следующих разделах мы рассмотрим семантику языка, регулирующую передачу и обнаружение исключений, а также несколько примеров.

Передача исключения

Чтобы методу уведомить вызвавший его метод, что возникла ошибка, он использует ключевое слово throw.

throw [выражение];

Мы рассмотрим разные способы передачи исключений чуть позже. Сейчас достаточно представлять себе, что при передаче исключения вам нужно передать объект типа System.Exception (или производный класс). Далее приведен пример метода, определившего, что произошла неисправимая ошибка и ему нужно передать исключение вызывающему методу. Обратите внимание, как создается новый экземпляр объекта System. Exceptions и передается вызывающему методу.

public void SomeMethodO {

// Обнаружена ошибка.

throw new Exception(); }

Улавливание исключения

Если метод может передавать исключения, должна быть обратная сторона, которая находит это исключение. Ключевое слово catch определяет блок кода, который выполнится при возникновении исключения данного типа. Содержащийся в этом блоке код называется обработчиком исключения.

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

Для обнаружения исключения нужно ограничить код, который вы собираетесь выполнить, блоком try, а затем указать, какие типы исключений этот код может обрабатывать в блоке catch. Все операторы из блока try будут обрабатываться по порядку, если только один из вызванных методов не передаст исключение. Если это произойдет, управление будет передано на первую строку соответствующего блока catch. Под " соответствующим блоком" я подразумеваю блок, определенный для улавливания исключений данного типа. Вот пример метода (Foo), вызывающего и обнаруживающего исключения, посылаемые другим методом (Ваг):

public void Foo() {

try

{

Bar();

}

catch(System.Exception e)

{

// Обработка ошибки.

> }

У вас может возникнуть вопрос: " Что будет, если Ваг передаст исключение, a Foo его не уловит? " (Это может иметь место, если обращение к Ваг не содержится в блоке try.) Результат зависит от структуры приложения. При передаче исключения управление передается по стеку вызовов наверх, пока не будет найден блок catch для исключения данного типа. Если метод с подходящим блоком catch не обнаруживается, приложение прерывается. Следовательно, если один метод вызывает другой — передающий исключение — структура приложения должна быть такова, чтобы метод в стеке вызовов смог обработать исключение.

 

ПРОСТРАНСТВО ИМЕН

Пространство имен (namespace) является фундаментальной концепцией C++. Пространство имен - это группа имен, в которой имена не совпадают. Исключением являются имена перегружаемых функций и переменные с различными областями действия. Имена в различных пространствах имен не конфликтуют. Например, можно использовать имя my_adress в двух различных классах (это же относится к структурам и объединениям). C++ также позволяет определить пространства имен при помощи ключевого слова namespace. Такие пространства имен вводятся для снижения вероятности конфликта имен и полезны в случае использования имен из нескольких различных библиотек.

Спецификатор namespace определяет пространство имен функций, классов и переменных, находящихся в отдельной области видимости. Вообще namespace определяет группу символов, представляющих собой названия или имена функций, классов или переменных. Примером такого определения области видимости является область видимости членов класса.

Синтаксис:

namespace name
{
// объявления и определения имен
}

Аргументом спецификатора namespace (то есть name) является идентификатор пространства имен.

Чтобы обратиться к чему-нибудь в пространстве namespace_name, достаточно обратиться непосредственно к члену, используя оператор определения области видимости (::): namespace_name:: member.

Однако, при многократном использовании члена member такая запись становится слишком громоздкой. Инструкция using заставляет компилятор признавать дальнейшее использование этому члену пространства namespace_name без дополнительного определения имени этого пространства:

using namespace_name:: member;

Инструкция using namespace заставляет компилятор признавать все члены пространства имен namespace_name:

using namespace namespace_name;

В приведенном ниже примере глобальные переменные Cary и Hugh объявляются в пространстве имен grants:

namespace grants
{
int Cary = 0;
int Hugh = 1;
}

Вне пространства имен grants переменные могут быть упомянуты как grants:: Cary и grants:: Hugh. Но можно сократить эту запись, если добавить такую инструкцию:

using grants:: Cary;

Теперь имя Cary может использоваться в последующих инструкциях без дополнительного определения. Чтобы иметь возможность ссылаться на обе переменные без определения имени пространства, достаточно написать

using namespace grants;

 

Ключевое слово namespace позволяет разделить глобальное пространство имен путем создания некоторой декларативной области. По сути, пространство имен определяет область видимости. Общая форма задания пространства имен
имеет следующий вид.

namespace имя { //Объявления }

Помимо именованных, можно иметь и безымянные пространства имен.

namespace { //Объявления }

Безымянные пространства имен позволяют установить уникальные идентификаторы, которые известны только внутри области видимости одного файла.

Безымянные пространства имен позволяют установить уникальные идентификаторы, которые известны только внутри области видимости одного файла.

Приведем пример использования ключевого слова namespace.

namespace MyNameSpace { int i, k; void myfunc(int j) { cout < < j; }}

Здесь переменные i, k и функция myfunc() являются частью области видимости, определенной пространством имен MyNameSpace.

Поскольку пространство имен определяет область видимости, для доступа к определенным внутри нее объектам необходимо использовать оператор разрешения видимости. Например, чтобы присвоить значение 10 переменной i, необходимо использовать следующий оператор.

MyNameSpace:: i = 10;





© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.