►Как работает полиморфизм...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.срр на прилагаемом компакт-диске, чтобы лучше ознакомиться с полиморфизмом.»
[Диск]
Больше книг — больше знаний!
Заберите 20% скидку на все книги Литрес с нашим промокодом
ПОЛУЧИТЬ СКИДКУ