}
catch( runtime_error &re ) {
}
catch( overflow_error eobj ) {
}
}
Упражнение 19.8
Дана программа на C++:
int main() {
// использование стандартной библиотеки
}
Модифицируйте main() так, чтобы она перехватывала все исключения, возбуждаемые функциями стандартной библиотеки. Обработчики должны печатать сообщение об ошибке, ассоциированное с исключением, а затем вызывать функцию abort() (она определена в заголовочном файле ) для завершения main().
19.3. Разрешение перегрузки и наследование A
* Наследование классов оказывает влияние на все аспекты разрешения перегрузки функций (см. раздел 9.2). Напомним, что эта процедура состоит из трех шагов: Отбор функций-кандидатов.
* Отбор устоявших функций.
* Выбор наилучшей из устоявших функции.
Отбор функций-кандидатов зависит от наследования потому, что на этом шаге принимаются во внимание функции, ассоциированные с базовыми классами, – как их функции-члены, так и функции, объявленные в тех же пространствах имен, где определены базовые классы. Отбор устоявших функций также зависит от наследования, поскольку множество преобразований формальных параметров функции в фактические аргументы расширяется пользовательскими преобразованиями. Кроме того, наследование оказывает влияние на ранжирование последовательностей трансформаций аргументов, а значит, и на выбор наилучшей из устоявших функции. В данном разделе мы рассмотрим влияние наследования на эти три шага разрешения перегрузки более подробно.
19.3.1. Функции-кандидаты
Наследование влияет на первый шаг процедуры разрешения перегрузки функции – формирование множества кандидатов для данного вызова, причем это влияние может быть различным в зависимости от того, рассматривается ли вызов обычной функции вида
func( args );
или функции-члена с помощью операторов доступа "точка" или "стрелка":
object.memfunc( args );
pointer-memfunc( args );
В данном разделе мы изучим оба случая.
Если аргумент обычной функции имеет тип класса, ссылки или указателя на тип класса, и класс определен в пространстве имен, то кандидатами будут все одноименные функции, объявленные в этом пространстве, даже если они невидимы в точке вызова (подробнее об этом говорилось в разделе 15.10). Если аргумент при наследовании имеет тип класса, ссылки или указателя на тип класса, и у этого класса есть базовые, то в множество кандидатов добавляются также функции, объявленные в тех пространствах имен, где определены базовые классы. Например:
namespace NS {
class ZooAnimal { /* ... */ };
void display( const ZooAnimal& );
}
// базовый класс Bear объявлен в пространстве имен NS
class Bear : public NS::ZooAnimal { };
int main() {
Bear baloo;
display( baloo );
return 0;
}
Аргумент baloo имеет тип класса Bear. Кандидатами для вызова display() будут не только функции, объявления которых видимы в точке ее вызова, но также и те, что объявлены в пространствах имен, в которых объявлены класс Bear и его базовый класс ZooAnimal. Поэтому в множество кандидатов добавляется функция display(const ZooAnimal&), объявленная в пространстве имен NS.
Если аргумент имеет тип класса и в определении этого класса объявлены функции-друзья с тем же именем, что и вызванная функция, то эти друзья также будут кандидатами, даже если их объявления не видны в точке вызова (см. раздел 15.10). Если аргумент при наследовании имеет тип класса, у которого есть базовые, то в множество кандидатов добавляются одноименные функции-друзья каждого из них. Предположим, что в предыдущем примере display() объявлена как функция-друг ZooAnimal:
namespace NS {
class ZooAnimal {
friend void display( const ZooAnimal& );
};
}
// базовый класс Bear объявлен в пространстве имен NS
class Bear : public NS::ZooAnimal { };
int main() {
Bear baloo;
display( baloo );
return 0;
}
Аргумент baloo функции display() имеет тип Bear. В его базовом классе ZooAnimal функция display() объявлена другом, поэтому она является членом пространства имен NS, хотя явно в нем не объявлена. При обычном просмотре NS она не была бы найдена. Однако поскольку аргумент display() имеет тип Bear, то объявленная в ZooAnimal функция-друг добавляется в множество кандидатов.
* Таким образом, если при вызове обычной функции задан аргумент, который представляет собой объект класса, ссылку или указатель на объект класса, то множество функций-кандидатов является объединением следующих множеств: функций, видимых в точке вызова;