- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Язык программирования C++. Пятое издание - Стенли Липпман
Шрифт:
Интервал:
Закладка:
void foo(int); // по умолчанию открыты
protected:
int ival;
char cval;
};
class VMI : public Derived1, public Derived2 { };
18.3.5. Конструкторы и виртуальное наследование
При виртуальном наследовании виртуальный базовый класс инициализируется конструктором самого последнего производного класса. В рассматриваемом примере при создании объекта класса Panda инициализацию членов базового класса ZooAnimal контролирует конструктор класса Panda.
Чтобы понять это правило, рассмотрим происходящее при применении обычных правил инициализации. В этом случае объект виртуального базового класса мог бы быть инициализирован несколько раз. Он был бы инициализирован вдоль каждой ветви наследования, содержащей этот виртуальный базовый класс. В данном примере, если бы к классу ZooAnimal применялись обычные правила инициализации, то части Bear и Raccoon инициализировали бы часть ZooAnimal объекта класса Panda.
Конечно, каждый базовый класс в иерархии объекта мог бы в некоторый момент быть "более производным". Поскольку вполне можно создавать независимые объекты класса, производного от виртуального базового класса, конструкторы в этом классе должны инициализировать его виртуальный базовый класс. Например, когда в рассматриваемой иерархии создается объект класса Bear (или Raccoon), никакого дальнейшего применения производного класса нет. В данном случае конструкторы класса Bear (или Raccoon) непосредственно инициализируют базовую часть ZooAnimal, как обычно:
Bear::Bear(std::string name, bool onExhibit) :
ZooAnimal(name, onExhibit, "Bear") { }
Raccoon::Raccoon(std::string name, bool onExhibit) :
ZooAnimal(name, onExhibit, "Raccoon") { }
Когда создается объект класса Panda, он является наиболее производным типом и контролирует инициализацию совместно используемого базового класса ZooAnimal. Даже при том, что класс ZooAnimal не является прямым базовым классом для класса Panda, часть ZooAnimal инициализирует конструктор класса Panda:
Panda::Panda(std::string name, bool onExhibit)
: ZooAnimal(name, onExhibit, "Panda"),
Bear(name, onExhibit),
Raccoon(name, onExhibit),
Endangered(Endangered::critical),
sleeping_flag(false) { }
Как создается объект при виртуальном наследованииПорядок создания объекта с виртуальным базовым классом немного отличается от обычного: сначала инициализируется часть виртуального базового класса с использованием инициализаторов, предоставленных в конструкторе для наиболее производного класса. Как только создана часть виртуального базового класса, создаются части прямых базовых классов в порядке их расположения в списке наследования.
Например, объект класса Panda создается так.
• Сначала создается часть виртуального базового класса ZooAnimal. При этом используются инициализаторы из списка инициализации конструктора класса Panda.
• Затем создается часть Bear.
• Затем создается часть Raccoon.
• Следующей создается часть прямого базового класса Endangered.
• Наконец создается часть Panda.
Если конструктор класса Panda не инициализирует явно часть базового класса ZooAnimal, будет использован стандартный конструктор класса ZooAnimal. Если у класса ZooAnimal нет стандартного конструктора, произойдет ошибка.
Части виртуальных базовых классов всегда создаются до частей обычных базовых классов, независимо от того, где они располагаются в иерархии наследования.
Порядок выполнения конструкторов и деструкторовУ класса может быть несколько виртуальных базовых классов. В этом случае части виртуальных классов создаются в порядке их расположения в списке наследования. Например, в следующей иерархии наследования у класса TeddyBear (МедвежонокТедди) есть два виртуальных базовых класса: прямой виртуальный базовый класс ToyAnimal (ИгрушечноеЖивотное) и косвенный базовый класс ZooAnimal, от которого происходит класс Bear:
class Character { /* ... */ };
class BookCharacter : public Character { /* ... */ };
class ToyAnimal { /* ... */ };
class TeddyBear : public BookCharacter,
public Bear, public virtual ToyAnimal
{ / * ... * / };
Чтобы выявить наличие виртуальных базовых классов, прямые базовые классы просматриваются в порядке объявления. Если это так, то сначала создаются части виртуальных базовых классов, затем выполняются конструкторы обычных, не виртуальных базовых классов в порядке их объявления. Таким образом, чтобы создать объект класса TeddyBear, конструкторы его частей вызываются в следующем порядке:
ZooAnimal(); // виртуальный базовый класс Bear
ToyAnimal(); // прямой виртуальный базовый класс
Character(); // косвенный базовый класс первого не виртуального
// базового класса
BookCharacter(); // первый прямой не виртуальный базовый класс
Bear(); // второй прямой не виртуальный базовый класс
TeddyBear(); // наиболее производный класс
Тот же порядок создания используется в синтезируемом конструкторе копий и конструкторах перемещения, в синтезируемых операторах присвоения члены присваиваются в том же порядке. Вызов деструкторов базовых классов осуществляется в порядке, обратном порядку вызова конструкторов. Часть TeddyBear будет удалена сначала, а часть ZooAnimal — последней.
Упражнения раздела 18.3.5Упражнение 18.29. Имеется следующая иерархия классов:
class Class { ... };
class Base : public Class { ... };
class D1 : virtual public Base { ... };
class D2 : virtual public Base { ... };
class MI : public D1, public D2 { ... };
class Final : public MI, public Class { ... };
(a) Каков порядок вызова конструкторов и деструкторов объектов класса Final?
(b) Сколько внутренних объектов класса Base находится в объекте класса Final? А сколько внутренних объектов класса Class?
(c) Какие из следующих случаев присвоения приведут к ошибке во время компиляции?
Base *pb; Class *pc; MI *pmi; D2 *pd2;
(a) pb = new Class; (b) pc = new Final;
(c) pmi = pb; (d) pd2 = pmi;
Упражнение 18.30. Определите в классе Base стандартный конструктор, конструктор копий и конструктор с параметром типа int. Определите те же три конструктора в каждом производном классе. Каждый конструктор должен использовать свой аргумент для инициализации своей части Base.
Резюме
Язык С++ применяется для решения широкого диапазона проблем: от требующих лишь нескольких часов работы до занимающих годы работы больших групп разработчиков. Некоторые из средств языка С++ наиболее полезны при создании крупномасштабных приложений. Имеется в виду обработка исключений, пространства имен и множественное или виртуальное наследование.
Обработка исключений позволяет отделить ту часть кода, где может произойти ошибка, от той части кода, где она обрабатывается. При передаче исключения выполнение текущей функции приостанавливается и начинается поиск ближайшей директивы catch. Локальные переменные, определенные в покидаемых при поиске директив catch функциях, удаляются в ходе обработки исключения.
Пространства имен — это механизм управления большими и сложными приложениями, формируемыми из кода, созданного независимыми поставщиками. Пространство имен является областью видимости, в которой могут быть определены объекты, типы, функции, шаблоны и другие пространства имен. Стандартная библиотека определена в пространстве имен std.
С концептуальной точки зрения множественное наследование — довольно простое понятие: производный класс может быть унаследован от нескольких прямых базовых классов. Объект производного класса состоит из частей, представляющих собой внутренние объекты всех своих базовых классов. Концепция действительно проста, но на практике сопряжена со многими сложностями. В частности, наследование от нескольких базовых классов создает вероятность конфликтов имен и в результате порождает неоднозначные обращения к именам из базовых частей объекта.
Если класс происходит от нескольких непосредственных базовых классов, не исключена ситуация, когда эти классы сами могут иметь общий базовый класс. В таких случаях промежуточные классы могут применить виртуальное наследование, позволяющее другим классам иерархии, унаследовавшим тот же базовый класс, совместно использовать его внутренний объект. Таким образом, объект производного класса будет иметь только одну совместно используемую копию внутреннего объекта виртуального базового класса.

