Спецификации исключений и указатели на функции
Спецификацию исключений можно задавать и при объявлении указателя на функцию. Например:
void (*pf)( int ) throw(string);
В этом объявлении говорится, что pf указывает на функцию, которая способна возбуждать только исключения типа string. Как и для объявлений функций, спецификации исключений в разных объявлениях одного и того же указателя не суммируются, они должны быть одинаковыми:
extern void (*pf) ( int ) throw(string);
// ошибка: отсутствует спецификация исключения
void (*pf)( int );
При работе с указателем на функцию со спецификацией исключений есть ограничения на тип указателя, используемого в качестве инициализатора или стоящего в правой части присваивания. Спецификации исключений обоих указателей не обязаны быть идентичными. Однако на указатель-инициализатор она должна накладывать столь же или более строгие ограничения, чем на инициализируемый указатель (или тот, которому присваивается значение). Например:
void recoup( int, int ) throw(exceptionType);
void no_problem() throw();
void doit( int, int ) throw(string, exceptionType);
// правильно: ограничения, накладываемые на спецификации
// исключений recoup() и pf1, одинаковы
void (*pf1)( int, int ) throw(exceptionType) = &recoup;
// правильно: ограничения, накладываемые на спецификацию исключений no_problem(), более строгие,
// чем для pf2
void (*pf2)( ) throw(string) = &no_problem;
// ошибка: ограничения, накладываемые на спецификацию
// исключений doit(), менее строгие, чем для pf3
//
void (*pf3)( int, int ) throw(string) = &doit;
Третья инициализация не имеет смысла. Объявление указателя гарантирует, что pf3 адресует функцию, которая может возбуждать только исключения типа string. Но doit() возбуждает также исключения типа exceptionType. Поскольку она не подходит под ограничения, накладываемые спецификацией исключений pf3, то не может служить корректным инициализатором для pf3, так что компилятор выдает ошибку.
Упражнение 11.9
В коде, разработанном для упражнения 11.8, измените объявление оператора operator[]() в классе IntArray, добавив спецификацию возбуждаемых им исключений. Модифицируйте программу так, чтобы operator[]() возбуждал исключение, не указанное в спецификации. Что при этом происходит?
Упражнение 11.10
Какие исключения может возбуждать функция, если ее спецификация исключений имеет вид throw()? А если у нее нет такой спецификации?
Упражнение 11.11
Какое из следующих присваиваний ошибочно? Почему?
void example() throw(string);
(a) void (*pf1)() = example;
(b) void (*pf2) throw() = example;