Прядок вызова конструкторов в производных классах
В C++ производный класс может быть порождён из любого числа непосредственных базовых классов. Наличие у производного класса более чем одного непосредственного базового класса называется множественным наследием. Синтаксически множественное наследование отличается от единичного наследования списком баз, состоящим более чем из одного элемента.
class A { }; class B { }; class C : public A, public B { };
При создании объектов-представителей производного класса, порядок расположения непосредственных базовых классов в списке баз определяет очерёдность вызова конструкторов умолчания. Этот порядок влияет и на очерёдность вызова деструкторов при уничтожении этих объектов. Но эти проблемы, также как и алгоритмы выделения памяти для базовых объектов, скорее всего, относятся к вопросам реализации. Вряд ли программист должен акцентировать на этом особое внимание. Более существенным является ограничение, согласно которому одно и то же имя класса не может входить более одного раза в список баз при объявлении производного класса. Это означает, что в наборе непосредственных базовых классов, которые участвуют в формировании производного класса не должно встречаться повторяющихся элементов. Вместе с тем, один и тот же класс может участвовать в формировании нескольких (а может быть и всех) непосредственных базовых классов данного производного класса. Так что для непрямых базовых классов, участвующих в формировании производного класса не существует никаких ограничений на количество вхождений в объявление производного класса:
class A { public: int x0, xA; }; class B : public A { public: int xB; }; class C : public A { public: int x0, xC; }; class D : public B, public C { public: int x0, xD; };
В этом примере класс A дважды используется при объявлении класса D в качестве непрямого базового класса. Для наглядного представления структуры производного класса также используются направленные ациклические графы, схемы классов и объектов.
Как и раньше, самый нижний узел направленного ациклического графа, а также нижний уровень схем соответствует производному классу и фрагменту объекта, представляющего производный класс. Такой фрагмент объекта мы будем называть производным фрагментом-представителем данного класса. Верхние узлы графа и верхние уровни схем классов и объектов соответствуют базовым классам и фрагментам объектов, представляющих базовые и непосредственные базовые классы. Эти фрагменты объекта мы будем называть базовыми и непосредственными базовыми фрагментами-представителями класса. Вот как выглядит граф ранее приведённого в качестве примера производного класса D:
A A B C D
А вот как представляется структура производного класса в виде неполной схемы класса. Базовые классы располагаются на этой схеме в порядке, который соответствует списку базовых элементов в описании базы производного класса. Этот же порядок будет использован при изображении диаграмм объектов. И это несмотря на то обстоятельство, что порядок вызова конструкторов базовых классов определяется конкретной реализацией. За порядком вызова конструкторов базовых классов всегда можно наблюдать после определения их собственных версий.
A B A C D
А вот и схема объекта производного класса.
D MyD; MyD ::= A (int)x0;
(int)xA;
B (int)xB;
A (int)x0; (int)xA;
C (int)x0;
D (int)x0;
(int)xD;
Первое, что бросается в глаза - это множество одноимённых переменных, "разбросанных" по базовым фрагментам объекта. Да и самих базовых фрагментов здесь немало.
Очевидно, что образующие объект базовые фрагменты-представители одного базового класса, по своей структуре неразличимы между собой. Несмотря на свою идентичность, все они обладают индивидуальной характеристикой - положением относительно производного фрагмента объекта. При множественном наследовании актуальной становится проблема неоднозначности, связанная с доступом к членам базовых классов. Доступ к члену базового класса является неоднозначным, если выражение доступа именует более одной функции, объекта (данные-члены класса также являются объектами), типа (об этом позже!) или перечислителя. Например, неоднозначность содержится в следующем операторе:
MyD.xA = 100; здесь предпринимается неудачная попытка изменения значения данного-члена базового фрагмента объекта MyD. Выражение доступа MyD.xA именует сразу две переменных xA. Разрешение неоднозначности сводится к построению такого выражения доступа, которое однозначно указывало бы функцию, объект, тип (об этом позже!) или перечислитель. Наша очередная задача сводится к описанию однозначных способов доступа к данным-членам класса, расположенным в разных базовых фрагментах объекта. И здесь мы впервые сталкиваемся с ограниченными возможностями операции доступа.
MyD.B::x0 = 100; Этот оператор обеспечивает изменение значения данного-члена базового фрагмента - представителя класса B. Здесь нет никаких проблем, поскольку непосредственный базовый класс B наследует данные-члены базового класса A. Поскольку в классе B отсутствуют данные-члены с именем x0, транслятор однозначно определяет принадлежность этого элемента. Итак, доступ к данному-члену базового класса A "со стороны" непосредственного базового класса B не представляет особых проблем.
- 99. Типы диаграмм языка uml
- 98. Унифицированный язык моделирования uml.
- 100. Диаграмма классов (class diagram).
- Концептуальная точка зрения — диаграмма классов описывает модель предметной области, в ней присутствуют только классы прикладных объектов;
- Точка зрения спецификации — диаграмма классов применяется при проектировании информационных систем;
- Точка зрения реализации — диаграмма классов содержит классы, используемые непосредственно в программном коде (при использовании объектно-ориентированных языков программирования).
- 102. Компонентно-ориентированное проектирование
- Объектно-ориентированное проектирование на основе иерархии классов.
- 93. Гетерогенные контейнеры adt шаблонов
- Компонентные классы как основа систем визуального программирования.
- Построение каркасов приложений в среде современных систем программирования.
- Производные классы: наследование.
- Термин наследование и применение к классам и их характеристикам
- Создание объекта производного класса.
- Расширение производного класса.
- Создание объекта производного класса и вызов конструкторов
- Производные классы: полиморфизм.
- Множественное наследование в классе, порождённом от нескольких родительских классов-предков.
- Производные классы: полиморфная функция
- Иерархия классов
- 39.Простые манипуляторы для управления потоком
- Прядок вызова конструкторов в производных классах
- Виртуальные базовые классы.
- Порядок построения виртуальных базовых классов.
- 25. Указатель на абстрактный класс.
- 28.Технология объектно-ориентированного программирования.
- Интерфейс пользователя и абстрактный класс.
- 35.Предопределенные объекты-потоки.
- 29. Применение шаблонов классов и шаблонов функций.
- 30.Объекты класса и указатели на объекты класса.
- 31.Члены данных объекта и указатели на члены данных класса.
- 32.Указатели на функции-члены класса и указатели на статические члены данных.
- 36.Стандартный ввод-вывод.
- 34.Создание и организация взаимодействие потоков ввода-вывода.
- 37.Методы позиционирования потоков.
- 38.Способы управления форматом выходных данных.
- 42.Организация ввода-вывода для пользовательского типа
- 40.Параметризованные манипуляторы и форматирующие функции.
- 41.Состояния потока.
- 43.Методы опроса и установки состояния потока.
- 44.Обработка ошибок в потоке через определение и установку состояния потока.
- 45.Последовательность действий при создании ostream.
- 46.Открытие и закрытие файла.
- 47.Методы ввода-вывода.
- 13.Преобразование типов в производных классах.
- 14.Разрешение области видимости в производных классах
- 15.Виртуальные функции.
- 16.Нестатические компонентные функции класса.
- 17.Применение виртуальных функций.
- 18.Вызов виртуальных функций в конструкторе.
- 19.Вызов полиморфных функций базового класса.
- 20.Вызов полиморфных функций через базовые классы.
- 21.Вызов виртуальной функции через таблицу виртуальных методов.
- 22.Ограничения на использование виртуальных функций.
- 23.Чистая виртуальная функция.
- 24.Абстрактный класс и его использование.
- 80.Контейнер объектов List
- 82.Контейнеры шаблонов fds (Fundamental Data Structures).
- 76.Класс итераторов объектов: внешние и внутренние итераторы.
- 81.Контейнер объектов Stack
- 71.Контейнерные классы объектов: понятие контейнерного класса.
- 72.Итераторы в контейнерных классах объектов как друзья класса.
- 48.Бинарные файлы.
- 49.Чтение бинарных файлов.
- 50.Запись в бинарные файлы.
- 51.Инициализация потоков с помощью конструктора.
- 52.Текстовые файлы для ввода-вывода.
- 60.Дружественные шаблоны.
- 53.Форматирование в памяти с использованием потоков strstream.
- 54.Шаблон класса.
- 69.Механизм обработки исключений.
- 56.Создание шаблонного класса.
- 57.Шаблон функции, объявление.
- 61.Функциональное замыкание при разработке приложений.
- 58.Запись шаблона функции с несколькими обобщенными аргументами.
- 65.Исключение как статический объект.
- 64.Объектно-ориентированный подход к обработке исключений.
- 66.Генерации исключения.
- 85.Гомогенные и гетерогенные контейнеры шаблонов fds.
- 63.Использование конструкторов и деструкторов в роли «вступления» и «заключения».
- 67.Операторы throw и catch.
- 68.Обработчик исключений.
- 70.Понятие контролируемого блока при обработке исключений.
- 84.Способы хранения элементов в контейнерах шаблонов fds.
- 83.Вектора и списки в контейнере шаблонов.
- Стандартные контейнеры библиотеки stl
- 86.Fds контейнеры шаблонов векторов
- 62.Функциональное замыкание через наследование.
- 87.Fds контейнеры шаблонов списков
- 89.Способы реализации и префиксы имен adt-контейнеров шаблонов.
- 88.Контейнеры шаблонов adt (Abstract Data Types) и их классификация.
- 90.Типы adt-контейнеров шаблонов.
- 91.Массивы adt-контейнеров шаблонов.
- 92.Стеки adt-контейнеров шаблонов.
- 78.Контейнер объектов Array
- 74.Класс контейнеров объектов: разбиение контейнеров на группы.
- 77.Иерархия классов итераторов объектов
- 79.Контейнер объектов SortedArray
- 73.Библиотека контейнерного класса структур данных.