Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


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




Полиморфизм является ключом (одним из связки), который способен открыть всю мощь объектно-ориентированного программирования. Он настолько важен, что язы- ки, не поддерживающие полиморфизм, не имеют права называться объектно- ориентированными.

Языки, которые поддерживают классы, но не поддерживают

физм, называются объектно-основанными. К таким языкам относится, например, Ada.

 

Без полиморфизма от наследования было бы мало толку. Позвольте привести еще один пример, чтобы вы поняли, почему это так. Представим себе, что я написал дей- ствительно сложную программу, использующую некий класс, который называется

не будем далеко ходить за примером — student . После нескольких месяцев разработ- ки, кодирования и тестирования я выставляю эту программу на всеобщее обозрение, чтобы услышать восторженные отзывы и критику от свих коллег. (Программа на- столько "крута", что уже заходит речь о передаче мне контрольного пакета Microsoft... но не будем опережать события.)

Проходит время, и мой босс просит добавить в программу возможность работы с аспирантами, которые хотя и очень похожи, но все-таки не идентичны обычным студентам (правда, аспиранты думают, что они совсем не похожи на студентов!). Мой босс не знает и не интересуется тем, что где-то глубоко в программе функция someFunction () вызывает функцию-член calcTuitio n () (такая уж работа у босса — ни о чем не думать и не волноваться...).

void

 

что эта функция должна делать...

s.

продолжается..-

 

Если бы C++ не поддерживал позднее связывание, мне бы пришлось отредактиро- вать функцию {) приблизительно так, как приведено                                    и добавить ее в класс GradusteStudent.

STUDENT 1

#define GRADUATESTUDENT 2

void                       s)

i

что эта функция должна

//добавим тип члена, который будет

текущий тип

switch

 

case STUDENT:

 

break;

case GRADUATESTUDENT:

 

break;

 

//..   продолжается...

 

 


Часть IV. Наследование


Мне бы пришлось добавить в класс переменную type. После этого я был бы вынужден добавить присвоения type STUDENT и type

к конструктору                                         Значение переменной typ e отражало бы теку- щий тип объекта s. Затем мне бы пришлось добавить проверяющие команды, пока- занные в приведенном выше фрагменте программы, везде, где вызываются переоп- ределяемые функции.

Это не так уж и трудно, если не обращать внимания на  три                         Во-первых, в данном  примере  описана только  одна функция. Представьте  себе,  что calcTuitio n () вызывается из нескольких мест и что этой функции придется выби- рать не между двумя, а между пятью или десятью классами. Маловероятно, что я най- ду все места в программе, которые надо отредактировать.

Во-вторых, я должен изменить (читай — сломать) код, который был отлажен и ра- ботал, а местами был довольно запутан. Редактирование может занять много времени и стать довольно скучной процедурой, что обычно ослабляет мое внимание. Любое изменение может оказаться ошибочным и конфликтовать с существующим кодом. Кто знает?..

И наконец, после того как я завершу редактирование, отладку и тестирование программы, я должен буду поддерживать две ее версии (если, конечно, не перестану поддерживать исходную). Это означает наличие двух потенциальных источников про- блем в случае выявления ошибок и необходимость отдельной системы систематиза- ции (как вам такая тавтология?), чтобы содержать все это в порядке.

А теперь представьте себе, что случится, когда мой босс захочет добавить                    один класс (босс он такой: на все способен...). Мне придется не только повторить весь процесс сначала, а поддерживать три версии программы!

При наличии полиморфизма все, что потребуется сделать, — это добавить новый подкласс и перекомпилировать программу. В принципе мне может понадобиться из- менить сам базовый класс, но только его и только в одном месте. Изменения в коде приложения будут сводиться к минимуму.

На некотором философском уровне есть еше более важные причины для поли- морфизма. Помните, как я готовил закуски в микроволновой печи? Можно сказать, что я действовал по принципу позднего связывания. Рецепт был таким: разогрейте за- куску в  печи. В нем не было сказано: если печь микроволновая, сделай так, а если конвекционная — эдак. В рецепте (читай — коде) предполагалось, что я (читай — тот, кто осуществляет позднее связывание) сам решу, какой именно разогрев (функцию- член) выбрать, в зависимости от типа используемой печи  (отдельного  экземпляра класса Oven) или ее вариаций (подклассов), например таких, как микроволновая печь Так думают люди, и так же создаются языки программирования: чтобы

дать людям возможность, не изменяя образа мыслей, создавать более точные модели реального мира.

 

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

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


Поделиться:



Последнее изменение этой страницы: 2019-04-19; Просмотров: 190; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.01 с.)
Главная | Случайная страница | Обратная связь