Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
###Cpp_лкц1_1.09_11_#дляБАК#29_01_12.doc
Скачиваний:
40
Добавлен:
29.04.2019
Размер:
6.42 Mб
Скачать

Часть II. Объектно-ориентированное программирование

}

// Методы, изменяющие значения полей:

void thinkO:

// Прочие методы:

void draw(int x. int у, int scale, int position):

}:

// Реализация класса daemon

void daemon: :think(){ /* ... */ }

void daemon::draw(int x. int y, int scale, int position)

{ /* ... Отрисовка daemon */ }

В классе daemon введено поле brain и метод think, определены собственные конструкторы и операция присваивания, а также переопределен метод отрисовки draw. Все поля класса monstr, операции (кроме присваивания) и методы getjiealth, get_ammo и changejiealth наследуются в классе daemon, а деструктор формируется по умолчанию.

Рассмотрим правила наследования различных методов.

Конструкторы не наследуются, поэтому производный класс должен иметь собственные конструкторы. Порядок вызова конструкторов определяется приведенными ниже правилами.

□ Если в конструкторе производного класса явный вызов конструктора базово- , го класса отсутствует, автоматически вызывается конструктор базового клас са по умолчанию (то есть тот, который можно вызвать без параметров). Это использовано в первом из конструкторов класса daemon.

  • Для иерархии, состоящей из нескольких уровней, конструкторы базовых классов вызываются начиная с самого верхнего уровня. После этого выполняются конструкторы тех элементов класса, которые являются объектами, в порядке их объявления в классе, а затем исполняется конструктор класса.

  • В случае нескольких базовых классов их конструкторы вызываются в порядке объявления.

ВНИМАНИЕ

Если конструктор базового класса требует указания параметров, он должен быть явным образом вызван в конструкторе производного класса в списке инициализации (это продемонстрировано в трех последних конструкторах).

Не наследуется и операция присваивания, поэтому ее также требуется явно определить в классе daemon. Обратите внимание на запись функции-операции: в ее теле применен явный вызов функции-операции присваивания из базового класса. Чтобы лучше представить себе синтаксис вызова, ключевое слово operator вместе со знаком операции можно интерпретировать как имя функции-операции.

Вызов функций базового класса предпочтительнее копирования фрагментов кода из функций базового класса в функции производного. Кроме сокращения объема кода, этим достигается упрощение модификации программы: изменения требуется вносить только в одну точку программы, что сокращает количество возможных ошибок.

Глава 5. Наследование

205

Ниже перечислены правила наследования деструкторов.

  • Деструкторы не наследуются, и если программист не описал в производном классе деструктор, он формируется по умолчанию и вызывает деструкторы всех базовых классов.

  • В отличие от конструкторов, при написании деструктора производного класса в нем не требуется явно вызывать деструкторы базовых классов, поскольку это будет сделано автоматически.

  • Для иерархии классов, состоящей из нескольких уровней, деструкторы вызываются в порядке, строго обратном вызову конструкторов: сначала вызывается деструктор класса, затем — деструкторы элементов класса, а потом деструктор базового класса.

Поля, унаследованные из класса monstr, недоступны функциям производного класса, поскольку они определены в базовом классе как private. Если функциям, определенным в daemon, требуется работать с этими полями, можно либо описать их в базовом классе как protected, либо обращаться к ним с помощью функций из monstr, либо явно переопределить их в daemon так, как было показано в предыдущем разделе (с. 201).

Рассматривая наследование методов, обратите внимание на то, что в классе daemon описан метод draw, переопределяющий метод с тем же именем в классе monstr (поскольку отрисовка различных персонажей, естественно, выполняется по-разному). Таким образом, производный класс может ие только дополнять, но и корректировать поведение базового класса1. Доступ к переопределенному методу базового класса для производного класса выполняется через имя, уточненное с помощью операции доступа к области видимости (::).

Виртуальные методы

Работа с объектами чаще всего производится через указатели. Указателю на базовый класс можно присвоить значение адреса объекта любого производного класса, например:

// Описывается указатель на базовый класс:

monstr *p;

// Указатель ссылается на объект производного класса:

р = new daemon; Вызов методов объекта происходит в соответствии с типом указателя, а не фактическим типом объекта, на который он ссылается, поэтому при выполнении оператора, например,

p->draw(l. 1. 1. 1):

будет вызван метод класса monstr, а не класса daemon, поскольку ссылки на методы разрешаются во время компоновки программы. Этот процесс называется ранним

1 Переопределять в производном классе рекомендуется только виртуальные методы (см. след. раздел).

206