Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Cpp_Страуструп.doc
Скачиваний:
16
Добавлен:
03.05.2015
Размер:
3.2 Mб
Скачать

1.4.4 Обработка особых ситуаций

По мере роста программ, а особенно при активном использовании

библиотек появляется необходимость стандартной обработки ошибок (или, в

более широком смысле, "особых ситуаций"). Языки Ада, Алгол-68 и Clu

поддерживают стандартный способ обработки особых ситуаций.

Снова вернемся к классу vector. Что нужно делать, когда операции

индексации передано значение индекса, выходящее за границы массива?

Создатель класса vector не знает, на что рассчитывает пользователь в таком

случае, а пользователь не может обнаружить подобную ошибку (если бы мог,

то эта ошибка вообще не возникла бы). Выход такой: создатель класса

обнаруживает ошибку выхода за границу массива, но только сообщает о ней

неизвестному пользователю. Пользователь сам принимает необходимые меры.

Например:

class vector {

// определение типа возможных особых ситуаций

class range { };

// ...

};

Вместо вызова функции ошибки в функции vector::operator[]() можно

перейти на ту часть программы, в которой обрабатываются особые ситуации.

Это называется "запустить особую ситуацию" ("throw the exception"):

int & vector::operator [] ( int i )

{

if ( i < 0 || sz <= i ) throw range ();

return v [ i ];

}

В результате из стека будет выбираться информация, помещаемая туда при

вызовах функций, до тех пор, пока не будет обнаружен обработчик особой

ситуации с типом range для класса вектор (vector::range); он и будет

выполняться.

Обработчик особых ситуаций можно определить только для специального

блока:

void f ( int i )

{

try

{

// в этом блоке обрабатываются особые ситуации

// с помощью определенного ниже обработчика

vector v ( i );

// ...

v [ i + 1 ] = 7; // приводит к особой ситуации range

// ...

g (); // может привести к особой ситуации range

// на некоторых векторах

}

catch ( vector::range )

{

error ( "f (): vector range error" );

return;

}

}

Использование особых ситуаций делает обработку ошибок более

упорядоченной и понятной. Обсуждение и подробности отложим до главы 9.

1.4.5 Преобразования типов

Определяемые пользователем преобразования типа, например, такие, как

преобразование числа с плавающей точкой в комплексное, которое необходимо

для конструктора complex(double), оказались очень полезными в С++.

Программист может задавать эти преобразования явно, а может полагаться на

транслятор, который выполняет их неявно в том случае, когда они необходимы

и однозначны:

complex a = complex ( 1 );

complex b = 1; // неявно: 1 -> complex ( 1 )

a = b + complex ( 2 );

a = b + 2; // неявно: 2 -> complex ( 2)

Преобразования типов нужны в С++ потому, что арифметические операции

со смешанными типами являются нормой для языков, используемых в числовых

задачах. Кроме того, большая часть пользовательских типов, используемых

для "вычислений" (например, матрицы, строки, машинные адреса) допускает

естественное преобразование в другие типы (или из других типов).

Преобразования типов способствуют более естественной записи программы:

complex a = 2;

complex b = a + 2; // это означает: operator + ( a, complex ( 2 ))

b = 2 + a; // это означает: operator + ( complex ( 2 ), a )

В обоих случаях для выполнения операции "+" нужна только одна функция,

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

класс complex описывается так, что для естественного и беспрепятственного

обобщения понятия числа нет необходимости что-то изменять для целых чисел.