Установка указателей производного класса на объекты базового класса



План занятия 23

 

Полиморфизм

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

Рассмотрим следующий пример полиморфизма. Предположим, мы создаем программу для биологического исследования, которая моделирует поведение различных типов животных. Классы Fish, Frog и Bird представляют три исследуемых типа животных (рыба, лягушка, птица). Пусть каждый их этих классов производится от класса Animal, имеющего функцию move (движение) и хранящего текущее местоположение животного. Каждый из производных классов реализует функцию move. Наша программа поддерживает массив указателей на объекты классов, производных от Animal. Чтобы моделировать перемещения животных, программа раз в секунду посылает каждому объекту одно и то же сообщение — а именно, move. Однако каждый конкретный тип животного откликается на это сообщение по-своему, — рыба может проплыть два метра, лягушка прыгнуть на три метра, а птица пролететь десять метров. Знание каждым объектом того, «как себя вести» (т.е. какое поведение присуще объектам данного типа) в ответ на один и тот же вызов функции, является ключевым моментом полиморфизма. Одно и то же сообщение (в данном случае move), посылаемое разнообразным объектам, приводит к «многим формам» поведения — отсюда и термин «полиморфизм».

Мы начнем с ряда небольших, узконаправленных примеров, которые приведут нас к пониманию виртуальных функций и динамического связывания — двух технологий, лежащих в основе полиморфизма. Ранее мы создали иерархию классов служащих, в которой класс BasePlusCommissionEmployee являлся производным от CommissionEmployee. Теперь мы исследуем отношения классов в этой иерархии более внимательно. Следующие  несколько примеров покажут каким образом указатели базового и производного классов могут устанавливаться на объекты базового и производного классов, и как эти указатели могут использоваться для активации элемент-функций этих объектов.

 

Вызов функций базового класса из объектов производного класса

Пример1(установка базового указателя на производный объект)

Строки 19-20 создают объект CommissionEmployee, а строка 23 — указатель на CommissionEmployee; строки 26-27 создают объект BasePlusCommissionEmployee, а строка 30 — указатель на BasePlusCommissionEmployee. Строки 37 и 39 используют имена объектов (соответственно CommissionEmployee и basePlusCommissionEmployee) для вызова элемент-функции print каждого объекта. Строка 42 присваивает адрес объекта базового класса CommissionEmployee указателю базового класса commissionEmployeePtr, который используется в строке 45 для активации элемент-функции print на этом объекте. Тем самым вызывается версия print, определенная в базовом классе CommissionEmployee. Аналогично строка 48 присваивает адрес объекта производного класса basePlusCommissionEmployee указателю производного класса basePlusCommissionEmployeePtr который используется в строке 52 для активации элемент-функции print на этом объекте. Тем самым вызывается версия print, определенная в производном классе BasePlusCommissionEmployee. Строка 55 присваивает затем адрес объекта производного класса basePlusCommissionEmployee указателю базового класса commissionEmployeePtr, который строка 59 использует для активации элемент-функции print. Компилятор C++ допускает такое «скрещивание», поскольку объект производного класса является объектом базового класса. Обратите внимание, что хотя указатель базового класса CommissionEmployee ссылается на объект производного класса BasePlusCommissionEmployee, вызывается функция print базового класса CommissionEmployee (а не функция производного класса BasePlusCommissionEmployee). Вывод: каждый из вызовов функции print показывает, что класс, функция которого активируется, определяется типом дескриптора (т.е. типом указателя или ссылки), используемого при вызове, а не типом объекта, на который дескриптор ссылается. Далее, когда мы введем виртуальные функции, мы продемонстрируем, как можно вызвать функцию класса объекта, а не класса дескриптора. Мы увидим, что это является критическим моментом реализации полиморфного поведения — центральной темы этой главы.

 

Установка указателей производного класса на объекты базового класса

Пример 2

В Примере 1 мы присвоили адрес объекта производного класса указателю базового класса и показали, что компилятор C++ допускает такое присваивание, так как объект производного класса является объектом базового класса. Здесь мы пробуем подойти к этому с другой стороны, устанавливая указатель производного класса на объект базового класса. [Замечание. Программа использует классы CommissionEmployee и BasePlusCommissionEmployee из Примера 1. Строки 8-9 создают объект CommissionEmployee, а строка 10 создает указатель BasePlusCommissionEmployee. Строка 14 пытается присвоить адрес объекта CommissionEmployee базового класса указателю basePlusCommissionEmployeePtr производного класса, но компилятор C++ генерирует сообщение об ошибке. Компилятор не допускает такого присваивания, поскольку CommissionEmployee не является BasePlusCommissionEmployee. Рассмотрим последствия в случае, если бы компилятор допускал подобное присваивание. Через указатель BasePlusCommissionEmployee мы можем вызвать любую элемент-функцию класса BasePlusCommissionEmployee, включая setBaseSalary, для объекта, на который ссылается указатель (т.е. объекта базового класса CommissionEmployee). Но объект CommissionEmployee не имеет элемент-функции setBaseSalary, как не имеет и элемента данных baseSalary, который она должна устанавливать. Это могло бы создать серьезные проблемы, поскольку setBaseSalary предполагает, что элемент baseSalary находится «на своем обычном месте» в объекте BasePlusCommissionEmployee. Это место в памяти не принадлежит объекту CommissionEmployee, так что элемент-функция setBaseSalary могла бы переписать какие-то другие важные данные, находящиеся в памяти, возможно,

принадлежащие другому объекту.

 


Дата добавления: 2018-08-06; просмотров: 206; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!