return 0;
}
Набор перегруженных функций print() в глобальной области видимости содержит функции print(int), print(double) и print(long double). Все они составят набор перегруженных функций, рассматриваемых при вызове функции print() в функции main(), даже в том случае, если первоначально эти функции были объявлены в различных областях видимости пространства имен.
Упражнение 18.20. С учетом следующего кода укажите, какие из функций (если они есть) соответствуют обращению к функции compute(). Перечислите функции-кандидаты и подходящие функции. Какая последовательность преобразований типов (если есть) будет применена к аргументу, чтобы он точно соответствовал параметру каждой подходящей функции?
namespace primerLib {
void compute();
void compute(const void *);
}
using primerLib::compute;
void compute(int);
void compute(double, double = 3.4);
void compute(char*, char* = 0);
void f() {
compute(0);
}
Что произойдет в случае, если объявления using будут расположены в функции main() перед обращением к функции compute()? Ответьте на те же вопросы, что и в предыдущем упражнении.
18.3. Множественное и виртуальное наследование
Для исследования множественного наследования используем пример иерархии из животного мира. Животные расположены на разных уровнях абстракции. Есть индивидуальные животные, различающееся по именам, такие как Ling-ling (Линг-линг), Mowgli (Маугли) и Balou (Балу). Каждое животное можно отнести к определенному виду; Линг-линг, например, это гигантская панда. Виды в свою очередь относятся к определенным семействам. Гигантская панда принадлежит к семейству медведей, а каждое семейство является членом сообщества животного мира.
Каждый уровень абстракции содержит разнообразные данные и функции. Определим класс ZooAnimal как абстрактный, призванный содержать информацию, которая является общей для всех животных и предоставляет открытый интерфейс. Класс Bear (Медведь) будет содержать информацию, которая является специфической для семейства медведей, и т.д.
Кроме классов животных, здесь можно определить дополнительные классы, которые инкапсулируют различные абстракции, например, животных, подвергающихся опасности. В данной реализации класс Panda (Панда) будет получен в результате множественного наследования от классов Bear и Endangered (Подвергающийся опасности).
18.3.1. Множественное наследование
Список наследования производного класса может содержать несколько базовых классов:
class Bear : public ZooAnimal { /* ... */ };
class Panda : public Bear, public Endangered { /* ... */ };
У каждого базового класса есть необязательный спецификатор доступа (см. раздел 15.5). Как обычно, если спецификатор доступа отсутствует, по умолчанию подразумевается спецификатор private (закрытый), если используется ключевое слово class, и public (открытый), если используется ключевое слово struct (см. раздел 15.5).
Как и при одиночным наследовании, список наследования может включить только те классы, которые были определены и не были определены как final (см. раздел 15.2.2). Язык С++ не налагает никаких ограничений на количество базовых классов, из которых может быть получен производный класс. Однако базовый класс может присутствовать в списке наследования только один раз.
При множественном наследовании объект производного класса внутренне содержит объекты каждого из своих базовых классов (см. раздел 15.2.2). Например, на рис. 18.2 у объекта Panda есть часть класса Bear (которая сама содержит часть ZooAnimal), часть класса Endangered и нестатические переменные-члены, если таковые имеются, объявленные в пределах класса Panda.
Рис. 18.2. Концептуальная структура объекта класса Panda