Программирование >>  Оптимизация возвращаемого значения 

1 ... 22 23 24 [ 25 ] 26 27 28 ... 96


bool operator = = {const T& Ihs , const T& rhs) throw {) {

return &lhs == &rhs ;

Шаблон определяет функцию operator == для всех типов. Для любой пары объектов одного и того же типа шаблон выдает true, если объекты имеют один и тот же адрес, в противном случае он возвращает false.

Данный шаблон содержит спецификацию исключений, согласно которой функции, созданные при его помощи, не будут генерировать никаких исключений. Но это не всегда так, потому что сохраняется возможность перегрузки operators (адресного оператора) для некоторых типов. При этом оператор operators может генерировать исключение при вызове из operator ==. Если возникает исключение, то произойдет нарушение спецификации, и вы все-таки попадете в функцию unexpected.

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

Избежать вызовов функции unexpected можно и другим способом: необходимо опустить спецификацию исключений в функциях, которые вызывают функции без спецификации исключений. Это просто соображения здравого смысла, но существует одна тонкость, которая касается разрешения пользователям регистрировать функции обратного вызова:

/ / Тип указателя функции для обратного вызова оконной системы, / / когда в этой системе происходит событие. typedefvoid (*CallBackPtr) (inteventXLocation,

int eventYLocation,

void*dataToPassBack); / / Класс оконной системы для перехода к функциям обратного вызова, зарегистрированным клиентами системы. classCallBack { public:

CallBack {CallBackPtr fPtr, void *dataToPassBack) :func(fPtr) , data(dataToPassBack){} voidmakeCallBack(int eventXlocation,

int eventYLocation) const throw ();

private:

CallBackPtrfunc; Функция, вызываемая

при обратномвызове. Void*data; Данные,передаваемые функции

}; обратного вызова.



* Увы, это невозможно, по крайней мере не будет переноситься. Хотя многие компиляторы и принимают код, приведенный здесь, комитет по стандартизации по непонятной причине установил, что спецификация исключений не должна появляться в определении типа . Если вам необходимо быстро решить эту проблему, придется создать макрос CallBackPtr.

/ / Чтобы реализовать обратный вызов, вызываем зарегистрированную функцию / / с координатами события / / и зарегистрированные данные. voidCallBack::makeCallBack{inteventXlocation, int eventYLocation) const throw {)

func{eventXlocation,eventYLocation, data);

В данном случае вызов func в функции makeCallBack иногда нарушает спецификацию исключений из-за того, что невозможно наверняка узнать, какие исключения могут быть сгенерированы функцией func.

Проблему легко устранить, подогнав спецификацию исключений в типе CallBackPtr*:

typedefvoid {*CallBackPtr) {inteventxLocation, int eventYLocation, void*dataToPassBack) throw{);

Если задан этот тип, происходит ошибка регистрации функции callback, и вы уже не застрахованы от генерации исключений.

Функция обратного вызова без спецификации исключений. voidcallBackFcnl, (inteventXLocation, inteventYLocation,

void*dataToPassBack) ; void *callBackData;

CallBackcl{callBackFcnl,callBackData) ;

Ошибка!CallBackFcnlможет генерировать исключение. Функция обратного вызова со спецификацией исключений.

voidcallBackFcn2 (inteventXLocation, inteventYLocation, void*dataToPassBack)throw 0;

callBackc2(callBackFcn2,callBackData) ;

Нормально, callBackFcn2имеет соответствующее определение ex.

Проверка спецификаций исключений при передаче указателей функции - относительно недавнее дополнение, появившееся в языке C-I-+, так что не удивляйтесь.



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

Третья методика, позволяющая избежать вызова функции unexpected, состоит в обработке исключений, которые могут генерироваться системой . Из этих исключений чаще всего встречается bad alloc, обычно генерируемое функциями operator new и operator new [ ] при ошибке выделения памяти (см. правило 8). При использовании в любой функции оператора new (см. там же) будьте готовы к тому, что в функции может возникнуть исключение bad alloc.

Хотя профилактика обычно лучше лечения, иногда предотвратить проблему сложнее, чем устранить ее последствия. Это значит, что в некоторых сл5аях справиться с неожиданными исключениями проще, чем предотвратить их появление.

Например, если вы пишете программы строго с использованием спецификаций исключений, но вынуждены вызывать функции из библиотек, в которых не предусмотрены такие спецификации, будет непрактично предотвращать возникновение неожиданных исключений, потому что для этого придется изменить код в библиотеках.

В подобных ситуациях вы можете использовать свойство языка С++ заменять исключения одного типа на другой. Например, предположим, что вы хотели бы заменить все неожиданные исключения на объекты TnnaUnexpectedException. Это нетрудно сделать следующим образом:

classUnexpectedException{}; Все объектынеожиданных

исключений будут заменены / / на объекты этого типа. voidconvertUnexpected{) Функция,которуюследует

{ / / вызывать при генерации

throwUnexpectedException{) ; неожиданногоисключения. }

В результате заданная по умолчанию функция unexpected будет заменяться на функцию convertUnexpected:

set unexpected (convertUnexpected);

После этого любое неожиданное исключение вызовет функцию convertUnexpected и будет заменено новым исгслючением типа UnexpectedException. Если нарушенная спецификация исключений имеет в своем составе тип UnexpectedException, то распространение исключения будет продолжено далее, как будто ничего и не произошло. (Если же спецификация исключений не содержит UnexpectedException, будет вызвана функция terminate, как если бы вы не заменяли unexpected.)

Другой способ перевода неожиданных исключений в стандартный тип основан на том, что если замена функции unexpected снова генерирует текущее исключение, то оно будет замещено новым исключением стандартного типа bad exception. Как же это осуществить? Очень просто:



1 ... 22 23 24 [ 25 ] 26 27 28 ... 96

© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика