Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология Образование Политология Производство Психология Стандартизация Технологии |
Глава Знакомствосвиртуальнымифункциями-членами:настоящиели
Полиморфизм является ключом (одним из связки), который способен открыть всю мощь объектно-ориентированного программирования. Он настолько важен, что язы- ки, не поддерживающие полиморфизм, не имеют права называться объектно- ориентированными. Языки, которые поддерживают классы, но не поддерживают физм, называются объектно-основанными. К таким языкам относится, например, 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; Просмотров: 213; Нарушение авторского права страницы