|
Программирование >> Инициализация объектов класса, структура
class bad alloc : public exception { ... public: bad alloc() throw(); bad alloc( const bad alloc s ) throw(); bad alloc s operator=( const bad alloc s ) throw(); virtual ~bad alloc() throw(); virtual const char* what() const throw(); Отметим, что если функция-член объявлена с модификатором const или volatile, как, скажем, what() в примере выше, то спецификация исключений должна идти после него. Во всех объявлениях одной и той же функции спецификации исключений обязаны содержать одинаковые типы. Если речь идет о функции-члене, определение которой находится вне определения класса, то спецификации исключений в этом определении и в #include <stdexcept> <stdexcept> определяет класс overflow error class transport { ... public: double cost( double, double ) throw ( overflow error ); ... ошибка: спецификация искчений отучается от той, что задана в объявлении в списке членов класса объявлении функции должны совпадать: double transport::cost( double rate, double distance ) { } Виртуальная функция в базовом классе может иметь спецификацию исключений, отличающуюся от той, что задана для замещающей функции-члена в производном. Однако в производном классе эта спецификация для виртуальной функции должна накладывать не меньше ограничений, чем в базовом: class Base { public: virtual double f1( double ) throw(); virtual int f2( int ) throw( int ); virtual string f3() throw( int, string ); ... class Derived : public Base { public: ошибка: спецификация исключений накладывает меньше ограничений, чем на Base::f1() double f1( double ) throw( string ); правильно: та же спецификация исключений, что и для Base::f2() int f2( int ) throw( int ); правильно: спецификация исключений f3() накладывает больше ограничений string f3( ) throw( int ); ... Почему спецификация исключений в производном классе должна накладывать не меньше ограничений, чем в базовом? В этом случае мы можем быть уверены, что вызов виртуальной функции из производного класса по указателю на тип базового не нарушит гарантируется, что исключения возбуждены не будут d compute( Base *pb ) throw() try { pb->f3( ); может возбудить исключение типа int или string обработка исключений, возбужденных в Base::f3() catch ( const string S ) { } catch ( int ) { } спецификацию исключений функции-члена базового класса: Объявление f3() в классе Base гарантирует, что эта функция возбуждает лишь исключения типа int или string. Следовательно, функция compute() включает catch-обработчики только для них. Поскольку спецификация исключений f3() в производном классе Derived накладывает больше ограничений, чем в базовом Base, то при программировании в согласии с интерфейсом класса Base наши ожидания не будут обмануты. В главе 11 мы говорили о том, что между типом возбужденного исключения и типом, заданным в спецификации исключений, не допускаются никакие преобразования. Однако если там указан тип класса, то функция может возбуждать исключения в виде объекта класса, открыто наследующего заданному. Аналогично, если имеется указатель на класс, то функции разрешено возбуждать исключения в виде указателя на объект класса, открыто наследующего заданному. Например: int main() { try { тело функции main() catch ( pushCnFull ) { ... catch ( popCnEmpty ) { ... блоки называются функциональными. (Mi упоминали их в разделе 11.2.) Например: Функциональный try-блок ассоциирует группу catch-обработчиков с телом функции. Если инструкция внутри тела возбуждает исключение, то поиск его обработчика ведется среди тех, что следуют за телом функции. Функциональный try-блок необходим для конструкторов класса. Почему? Определение имя класса( список параметров ) список инициализации членов: : член1(важение1 ) , инициазация член1 член2(важение2 ) , инициазация член2 тело функции: конструктора имеет следующий вид: { /* ... */ } в1ражение1 и в1ражение2 могут быть выражениями любого вида, в частности функциями, которые возбуждают исключения. class stackExcp : public Excp { }; class popCbEmpty : public stackExcp { }; class pushCnFull : public stackExcp { }; void stackManip() throw( stackExcp ) { ... Спецификация исключений указывает, что stackManip() может возбуждать исключения не только типа stackExcp, но также popCnEmpty и pushCnFull. Напомним, что класс, открыто наследующий базовому, представляет собой пример отношения ЯВЛЯЕТСЯ, т.е. является частным случае более общего базового класса. Поскольку popCnEmpty и pushCnFull - частные случаи stackExcp, они не нарушают спецификации исключений функции stackManip() . 19.2.7. Конструкторы и функциональные try-блоки Можно объявить функцию так, что все ее тело будет заключено в try-блок. Такие try-
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |