Глава 20. Наследование и полиморфизм___________________________555

И вызывая ДЛЯ ЭТИХ Employee функцию PrintData:

for (int count = 0; count < numberOfEmployees; count++) {

companyEmployee[count]->PrintData();

}

мы на каждом обороте цикла вызоваем не просто Employee:: PrintData. Наш указатель на класс Employee на самом деле действует так, как если бы он указывал на любой производный класс, или подкласс, класса Employee (не говоря уже, разумеется, об экземплярах самого Employee). Таким образом, если текущий служащий принадлежит к руководящему составу, то вызовется функция Manager:: Employee и т.д. Имя в программе (например, переменную), ведущее себя по-разному для разных производных от базового классов, называют полиморфным, имеющим много форм. Полиморфизм в объектно-ориентированном программировании' предоставляет программисту великую свободу, проистекающую из наследования, в обращении с объектами. Например, если вы вспомните иерархию нашей машиностроительной фирмы, у нас в иерархии был класс с именем EngineeringManager. Но экземпляр ЭТОГО класса МОГ бы рассматриваться не ТОЛЬКО как EngineeringManager, НО И как Engineer, ИЛИ Manager, ИЛИ SalariedEmployee, ИЛИ Employee. Когда ВЫ

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

Все рассмотренные нами демонстрационные приложения состоят из двух или более элементов управления: ползунковых регуляторов, индикаторов и "хордовых индикаторов" (chord gauges). Что происходит, когда нужно обновить изображение на экране и все элементы управления в окне нуждаются в перерисовке? Учитывая, что все элементы управления в OWL произошли от класса TControl, кто-нибудь может подумать, что в OWL существует некий гигантский оператор switch, который вызывает функцию paint ползункового регулятора, функцию paint индикатора и т. д. Разумеется, это абсурд. Как он смог бы догадаться, за какой меткой скрывается TChordGauge? Мы же только что создали этот класс! Точно так же, как в примере с машиностроительной фирмой, полиморфизм работает и в OWL. Поскольку все элементы управления произошли от TControl, то функции, объявленные виртуальными в TControl (или даже в базовом для TControl классе), в производных классах будут замещены собственными функциями-членами.

Как МЫ МОГЛИ бы Применить ПОЛИМОРФИЗМ В нашем Примере С TChordGauge?

Допустим, сейчас у нас есть только два "объекта", из которых состоит наш управляющий элемент: циферблат (полукруг и деления) и лицевая часть (стрелка), но в будущем их могло бы быть и больше. В принципе мы хотели бы вместо того, чтобы функция paint вызывала paintBorder и рисовала сама, иметь цикл, который бы выполнялся над массивом экземпляров некоторого класса (давайте назовем этот класс TChordGaugePart), используя полимор-