Лабораторная работа 7. Полиморфизм и виртуальные функции
Цели:
рассмотреть применение указателей на базовый класс в качестве указателей на производные классы;
научиться создавать виртуальные функции;
освоить использование чистых виртуальных функций и абстрактных классов.
Фундамент, на котором С++ строит свою поддержку полиморфизма, состоит из наследования и указателей на базовые классы. Конкретным средством, которое фактически реализует полиморфизм, является виртуальная функция.
Как вы знаете из предыдущей работы, наследование — это средство, позволяющее одному классу наследовать характеристики другого. Опираясь на понятие наследования, вы можете создать базовый класс, в котором будут определены характерные черты, общие для определенного круга объектов. Эти общие черты могут наследоваться другими, более специфическими классами, каждый из которых добавит к ним более частные средства, характерные для данного производного класса. Возможности наследования находят свое применение в понятии виртуальной функции. Виртуальные функции поддерживают полиморфизм, философию "одного интерфейса, многих методов", являющуюся одним из краеугольных камней объектно-ориентированного программирования.
Указатели на производные классы
Указатели на базовый и производный классы связаны друг с другом, чего мы не наблюдаем для указателей других типов. Как правило, указатель одного типа не может указывать на объект другого типа. Однако указатели базовых и производных классов выпадают из этого правила. В С++ указатель базового класса может быть использован в качестве указателя на объект любого другого класса, производного от этого базового. Предположив например, что у нас есть базовый класс В и производный от нем класс D. Любой указатель, объявленный как указатель на В, можно использовать для указания на объект типа D. Таким образом, если имеются объявления:
B *р; // указатель на объект типа В
B B_ob; // объект типа В
D D_ob; // объект типа D
то следующие предложения вполне правильны:
p = &В_оЬ; // р указывает на объект типа В
p = &D_ob; /* р указывает на объект типа D,
который является производным от В. */
Базовый указатель можно использовать только для обращения к тем частям производного объекта, которые наследованы от базовое класса. Так, в этом примере р можно использовать для обращения ко всем элементам D_ob, унаследованным от B_ob. Однако к элементам специфическим для D_ob, посредством р обратиться нельзя.
Еще необходимо усвоить, что хотя посредством базового указателя можно обратиться к производному объекту, обратное несправедливо. Вы не можете обратиться к объекту базового типа, используя указатель на производный класс.
Тот факт, что указатель на базовый тип может быть использован для указания на любой объект, производный от этого базового типа является исключительно важным и фундаментальным для С++. Как вы вскоре узнаете, эта возможность позволяет С++ реализовать полиморфизм времени выполнения.