►Как работает полиморфизм...245

Любой язык программирования может поддерживать раннее либо позднее связывание. Старые языки типа С в основном поддерживают раннее связывание. Более поздние языки, наподобие Java, поддерживают позднее связывание. С++ же поддерживает оба типа связывания.

Вас может удивить, что по умолчанию С++ использует раннее связывание. Если немного подумать, причина становится понятной. Во-первых, для достижения максимальной обратной совместимости с языком С в С++ используется такое же как и в С раннее связывание. Во-вторых, позднее связывание несколько менее эффективно и требует как выполнения дополнительного кода, так и дополнительных затрат памяти. Отцы-основатели С++ беспокоились о том, что любое изменение, которое они представят в С++ как усовершенствование его предшественника С, может стать поводом для неприятия этого языка в качестве системного языка программирования. Поэтому они сделали более эффективное раннее связывание используемым по умолчанию.

Последняя причина в том, что достаточно полезной для программиста оказывается возможность определить, будет ли переопределяться некоторая функция в будущем или нет. Этого оказалось достаточно, чтобы в С# Microsoft позволила программистам указывать, что некоторая функция будет непереопределимой ( по умолчанию все функции переопределимы ).

Чтобы сделать функцию-член полиморфной, программист на С++ должен пометить её ключевым словом virtual так, как это показано ниже.

    class Student

    {

      public :

        /* Раскомментируйте одну из двух следующих строк; одна выполняет раннее связывание calcTuition( ), а вторая — позднее */

        virtual float calcTuition( )

        {

            cout << "Функция Student::calcTuition" << endl ;

            return 0 ;

        }

    } ;

Ключевое слово virtual сообщает С++ о том, что calcTuition( ) является полиморфной функцией-членом. Это так называемое виртуальное объявление calcTuition( ) означает, что вызовы данной функции-члена будут связаны позже, если есть хоть какие-то сомнения по поводу типа объекта, для которого будет вызываться функция calcTuition( ) на этапе выполнения.

В приведённой ранее демонстрационной программе OverloadOverride calcTuition( ) вызывается через промежуточную функцию fn( ). Когда функции fn( ) передаётся объект базового класса, она вызывает функцию Student::calcTuition( ). Но когда функции передаётся объект подкласса, этот же вызов обращается к функции GraduateStudent::calcTuition( ).

Запуск программы приведёт к выводу на экран таких строк:

    Функция Student::calcTuition

    Функция GraduateStudent::calcTuition

    Press any key to continue...

«Если вы уже освоились с отладчиком вашей среды С++, настоятельно рекомендую выполнить этот пример в пошаговом режиме.»

[Технические подробности]

_________________

245 стр. Глава 21. Знакомство с виртуальными функциями-членами: настоящие ли они

«Достаточно объявить функцию виртуальной только в базовом классе. Виртуальность наследуется подклассами автоматически. Однако в этой книге я следую стандарту кодирования, в соответствии с которым функции объявляются виртуальными везде.»

[Советы]

«Обратитесь к программе PolymorphicNachos.срр на прилагаемом компакт-диске, чтобы лучше ознакомиться с полиморфизмом.»

[Диск]