Как видите, класс second_d теперь использует версию функции who(), которая определена в классе first_d, поскольку она ближе всех в иерархической цепочке классов.
Как отмечалось в начале этой главы, виртуальные функции в сочетании с производными типами позволяют C++ поддерживать динамический полиморфизм. Полиморфизм существенен для объектно-ориентированного программирования по одной важной причине: он обеспечивает возможность некоторому обобщенному классу определять функции, которые будут использовать все производные от него классы, причем производный класс может определить собственную реализацию некоторых или всех этих функций. Иногда эта идея выражается следующим образом: базовый класс диктует общий интерфейс, который будет иметь любой объект, выведенный из этого класса, но позволяет при этом производному классу определить метод, используемый для реализации этого интерфейса. Вот почему для описания полиморфизма часто используется фраза "один интерфейс, множество методов".
Для успешного применения полиморфизма необходимо понимать, что базовый и производный классы образуют иерархию, развитие которой направлено от большей к меньшей степени обобщения (т.е. от базового класса к производному). При корректной разработке базовый класс обеспечивает все элементы, которые производный класс может использовать напрямую. Он также определяет функции, которые производный класс должен реализовать самостоятельно. Это дает производному классу гибкость в определении собственных методов, но в то же время обязывает использовать общий интерфейс. Другими словами, поскольку формат интерфейса определяется базовым классом, любой производный класс должен разделять этот общий интерфейс. Таким образом, использование виртуальных функций позволяет базовому классу определять обобщенный интерфейс, который будет использован всеми производными классами.
Теперь у вас может возникнуть вопрос: почему же так важен общий интерфейс со множеством реализаций? Ответ снова возвращает нас к основной побудительной причине возникновения объектно-ориентированного программирования: такой интерфейс позволяет программисту справляться со все возрастающей сложностью программ. Например, если корректно разработать программу, то можно быть уверенным в том, что ко всем объектам, выведенным из базового класса, можно будет получить доступ единым (общим для всех) способом, несмотря на то, что конкретные действия у одного производного класса могут отличаться от действий у другого. Это означает, что программисту придется помнить только один интерфейс, а не великое их множество. Кроме того, производный класс волен использовать любые или все функции, предоставленные базовым классом. Другими словами, разработчику производного класса не нужно заново изобретать элементы, уже имеющиеся в базовом классе. Более того, отделение интерфейса от реализации позволяет создавать библиотеки классов, написанием которых могут заниматься сторонние организации. Корректно реализованные библиотеки должны предоставлять общий интерфейс, который программист может использовать для выведения классов в соответствии со своими конкретными потребностями. Например, как библиотека базовых классов Microsoft (Microsoft Foundation Classes — MFC), так и более новая библиотека классов .NET Framework Windows Forms поддерживают Windows-программирование. Использование этих классов позволяет писать программы, которые могут унаследовать множество функций, нужных любой Windows-программе. Вам понадобится лишь добавить в нее средства, уникальные для вашего приложения. Это — большое подспорье при программировании сложных систем.
Чтобы вы могли получить представление о силе принципа "один интерфейс, множество методов", рассмотрим следующую короткую программу. Она создает базовый класс figure, предназначенный для хранения размеров различных двумерных объектов и вычисления их площадей. Функция set_dim() является стандартной функцией-членом, поскольку эта операция подходит для всех производных классов. Однако функция show_area() объявлена как виртуальная, так как методы вычисления площади различных объектов будут разными. Программа использует базовый класс figure для выведения двух специальных классов rectangle и triangle.
#include <iostream>
using namespace std;
class figure {