C++.Бархатный путь



         

Виртуальные функции


Очередная модификация базового класса приводит к неожиданным последствиям. Эта модификация состоит в изменении спецификатора функции-члена базового класса. Мы (впервые!) используем спецификатор virtual в объявлении функции. Функции, объявленные со спецификатором virtual, называются виртуальными функциями. Введение виртуальных функций в объявление базового класса (всего лишь один спецификатор) имеет столь значительные последствия для методологии объектно-ориентированного программирования, что мы лишний раз приведём модифицированное объявление класса A:

class A { public: virtual int Fun1(int); };

Один дополнительный спецификатор в объявлении функции и больше никаких (пока никаких) изменений в объявлениях производных классов. Как всегда, очень простая функция main(). В ней мы определяем указатель на объект базового класса, настраиваем его на объект производного типа, после чего по указателю мы вызываем функцию Fun1():

void main () { A *pObj; A MyA; AB MyAB; pObj = &MyA; pObj->Fun1(1); AC MyAC; pObj = &MyAC; pObj->Fun1(1); }

Если бы не спецификатор virtual, результат выполнения выражения вызова pObj->Fun1(1);

был бы очевиден: как известно, выбор функции определяется типом указателя.

Однако спецификатор virtual меняет всё дело. Теперь выбор функции определяется типом объекта, на который настраивается указатель базового класса. Если в производном классе объявляется нестатическая функция, у которой имя, тип возвращаемого значения и список параметров совпадают с аналогичными характеристиками виртуальной функции базового класса, то в результате выполнения выражения вызова вызывается функция-член производного класса.

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




Содержание  Назад  Вперед