Перегрузка функции базового класса называется переопределением ( overriding ) функции базового класса. Такое новое название используется, чтобы отличать этот более сложный случай от нормальной перегрузки.

<p id="chapter21.1"><strong>►Зачем нужен полиморфизм...243</strong></p>

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

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

[Советы]

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

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

    void someFunction( Student&s )

    {

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

        s.calcTuition( ) ;

        /* ...функция продолжается... */

    }

Если бы С++ не поддерживал позднее связывание, мне бы пришлось отредактировать функцию someFunction( ) приблизительно так, как показано ниже, и добавить её в класс GraduateStudent.

_________________

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

    #define STUDENT 1

    #define GRADUATESTUDENT 2

    void someFunction( Student& s )

    {

        /* ...то, что эта функция должна делать... Добавим тип члена, который будет индицировать текущий тип объекта */

        switch ( s.type )

        {

            case STUDENT :

                s.Student::calcTuition( ) ;

                break ;

            case GRADUATESTUDENT :

                s.GraduateStudent::calcTuition( ) ;

                break ;

        }

        /* ...функция продолжается... */

    }

Мне бы пришлось добавить в класс переменную type. После этого я был бы вынужден добавить присвоения type = STUDENT к конструктору Student и type = GRADUATESTUDENT к конструктору GraduateStudent. Значение переменной type отражало бы текущий тип объекта s. Затем мне пришлось бы добавить проверяющие команды, показанные в приведённом выше фрагменте программы, везде, где вызываются переопределяемые функции.

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

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

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

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

Перейти на страницу:

Все книги серии Для чайников

Похожие книги