Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Otvety_na_voprosy.docx
Скачиваний:
10
Добавлен:
15.04.2019
Размер:
75 Кб
Скачать
☆

21.Инициализация объектов при наследовании

Все действия по инициализации выполняются этап за этапом в порядке наследования классов, т.е. сначала п.1 для класса Object , потом п.1 для следующего класса и т.д., потом п.2 в том же порядке и т.д.

При первом обращении к классу выделяется память под статические поля класса и выполняется их инициализация.Выполняется распределение памяти под создаваемый объект.Выполняются все инициализаторы нестатических полей класса.Выполняется вызов конструктора класса. При создании экземпляра производного класса сначала выполняется конструктор базового, а затем конструктор производного класса. Деструкторы выполняются в обратном порядке. При создании объектов базового класса выполняются конструктор и деструктор только данного базового класса.

22. Указатели на производный и базовый классы. Формат явного преобразования указателей на базовый класс.

Для настройки указателя на объект производного класса нам не потребовалось никаких дополнительных преобразований. Здесь важно только одно обстоятельство. Между классами должно существовать отношение наследования. Таким образом, проявляется важное свойство объектно-ориентированного программирования: УКАЗАТЕЛЬ НА БАЗОВЫЙ КЛАСС МОЖЕТ ССЫЛАТЬСЯ НА ОБЪЕКТЫ - ПРОИЗВОДНЫХ КЛАССОВ. Подобное, на первый взгляд, странное обстоятельство имеет своё объяснение. Основной итог этого раздела заключается в следующем: указатель на объект базового класса можно настроить на объект производного типа. Через этот указатель можно "увидеть" лишь фрагмент объекта производного класса - его "базовую" часть - то, что объект получает в наследство от своих предков. Решение о том, какая функция должна быть вызвана, принимается транслятором. В момент выполнения программы всё уже давно решено. Какая функция будет вызвана из объекта производного типа - зависит от типа указателя, настроенного на данный объект. В этом случае мы наблюдаем классический пример статического связывания. Операция :: оставляет в "мёртвой зоне" целые фрагменты объектов. Однако возможность доступа к членам класса, которые оказались вне пределов досягаемости операции доступа всё же существует. Она обеспечивается указателями и операциями явного преобразования типа.

Идея состоит в том, чтобы, объявив указатель на объект-представитель базового класса, попытаться его настроить с помощью операций явного преобразования типа на соответствующий фрагмент объекта производного класса. В результате недосягаемые с помощью операции доступа фрагменты объекта превращаются в безымянные объекты простой конфигурации. Доступ к их членам в этом случае обеспечивается обычными операциями косвенного обращения. Рассмотрим несколько строк, которые демонстрируют такую технику работы с недосягаемыми фрагментами.

Очевидно, что можно обойтись без поэтапных преобразований и воспользоваться свойством коммутативности операции явного преобразования типа:

((A*)(C*)pObjD)->x0 = 5;

((A*)(B*)pObjD)->x0 = 55;

// Разным фрагментам - разные значения.

23.Виртуальный базовый класс

В языке С++ запрещено непосредственно передавать базовый класс в производный более одного раза, т.е. имя класса в списке базовых классов не может повторяться. Однако могут возникать ситуации, когда один производный класс косвенно может наследовать один и тот же базовый класс через другие базовые классы.Такое наследование вполне возможно и компилятор не выдаст сообщение об ошибке, а только предупредит, что наследуемый класс A также находится и в наследуемом классе B. Если один базовый класс косвенно наследуется в одном производном классе и наследуется с атрибутом virtual, то в экземпляр производного класса будет помещена только одна копия базового класса. Базовый класс объявляется как виртуальный только при наследовании - в списке базовых классов с указанием спецификатора virtual:

class A {...};

class B:virtual public A{...};

class C:virtual public A, public B {...};

Следует отметить, что если базовый класс наследуется производным как виртуальный, то его компоненты все равно доступны в производном классе. Отличие между обычным и виртуальным наследованием заключается в том, что когда класс наследует базовый класс более одного раза, то он будет содержать только одно вхождение базового класса.При виртуальном наследовании базовых классов в первую очередь вызываются конструкторы виртуальных базовых классов в порядке наследования. Так, в нашем примере первым будет вызван конструктор виртуального класса А, затем конструктор виртуального класса С, затем конструктор базового класса B, и последним будет вызван конструктор производного класса. Деструкторы вызываются в обратном порядке. В случае, если базовый класс C наследовался бы как не виртуальный, то порядок вызова конструкторов был бы следующий: конструктор класса А, конструктор класса В, конструктор класса С, конструктор класса D. И последнее, если базовый класс А наследовался бы как не виртуальный, то это привело бы к ошибке на стадии компиляции.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]