Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
програмирование 17-20.docx
Скачиваний:
1
Добавлен:
01.03.2025
Размер:
82.57 Кб
Скачать

Void f( int a ) throw( Range, Size, int, char* )

{

// тело функции

}

Здесь указано, что функция f() может заявить (прямо или косвенно) исключения

четырех заданных типов или производные от них, но не другие. Это

эквивалентно коду функции вида:

Void f( int a ) {

try {

// тело функции

}

catch( Range( ) ) {

throw; // повторно заявить то же исключение

}

catch( Size( ) ) {

throw; // повторно заявить то же исключение

}

catch( int ) {

throw; // повторно заявить то же исключение

}

catch( char* ) {

throw; // повторно заявить то же исключение

}

catch( . . . ) {

unexpected( );

}

}

Предполагается, что функция, определяемая без указания спецификации

исключительных ситуаций, может заявить исключение любого типа. Функция,

которая не может вообще генерировать исключений, должна описываться с

пустым списком:

Int g( void ) throw( ); // функция не заявляет каких-либо исключений

23

Спецификация исключения, однако, не контролируется на этапе

компиляции. Например, код

Void f( void ) throw( int ){ throw “This error message has type char* ”; }

не вызовет даже предупреждающего сообщения компилятора. Несоответствие

фактического типа заявленного исключения специфицированным будет

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

функции unexpected(). По умолчанию функция unexpected() вызывает другую

предопределенную функцию terminate(). Функция terminate() вызывается также,

если исключение заявлено, но не обработано или если средства обработки

исключений обнаружили разрушение стека.

Прототипы функций terminate() и unexpected() содержатся в заголовочном

файле except.h. По умолчанию функция terminate() просто завершает программу,

вызывая функцию abort(). Однако существует возможность установить

собственные функции terminate() и unexpected(), используя set_terminate() и

set_unexpected() соответственно [2].

Инкапсуляция и возможность подмены реакции на необработанное или

неожиданное исключение оказывается весьма полезной при интегрировании

системы в новую среду. Например, при переносе несетевого приложения в

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

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

функцию unexpected().

Рассмотрим предложенный в [1] способ адаптации некоторой функции g()

к использованию в сети. Во-первых, определим класс, позволяющий

манипулировать значением функции unexpected() как ресурсом, согласно

рассмотренному выше приему управления ресурсами путем инициализации

локальных переменных:

#include <except.h>

class STC {

unexpected_function old;

public :

STC( unexpected_function f) { old = set_unexpected( f ); }

~STC( ) { set_unexpected( old ); }

};

Тип unexpected_function и прототип функции set_unexpected() описаны в

заголовочном файле except.h следующим образом:

typedef void( _RTLENTRY * unexpected_function ) ( ) ;

unexpected_function _RTLENTRY set_unexpected( unexpected_function );

24

Здесь используется макрос _RTLENTRY, определяющий правила вызова,

используемые стандартной библиотекой исполняющей системы (Standard Runtime

Library) [2].

Задание1 Прокомментируйте оператор typedef, расшифровав смысл имени

unexpected_function.

Во-вторых, определим функцию, подменяющую unexpected():