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