- •Введение
- •Как получить исходные тексты
- •Что требуется знать для чтения книги
- •Предисловие к первому изданию
- •Благодарности
- •1.3.Новая парадигма
- •Что читать дальше
- •Упражнения
- •2.7.3.Зацепление и связность
- •2.9. Выбор представления данных
- •Упражнения
- •Глава 3 Классы и методы
- •Упражнения
- •Глава 4 Сообщения, экземпляры и инициализация
- •Упражнения
- •Глава 5 Учебный пример: задача о восьми ферзях
- •Упражнения
- •Глава 6 Учебный пример: игра «Бильярд»
- •Упражнения
- •Глава 7 Наследование
- •7.6.Издержки наследования
- •Упражнения
- •Глава 8 Учебный пример: Пасьянс
- •8.4.1.Основание SuitPile
- •8.4.2.Колода DeckPile
- •Упражнения
- •9.1.1. «Быть экземпляром» и «включать как часть»
- •Упражнения
- •Глава 10 Подклассы и подтипы
- •Упражнения
- •Глава 11 Замещение и уточнение
- •Упражнения
- •Глава 12 Следствия наследования
- •Упражнения
- •Глава 13 Множественное наследование
- •13.1.Комплексные числа
- •Литература для дальнейшего чтения
- •Упражнения
- •Глава 14 Полиморфизм
- •Полиморфные переменные
- •Виртуальное и невиртуальное переопределение
- •Параметрическая перегрузка
- •Отложенные методы в C++
- •Обобщенные функции и шаблоны
- •Полиморфные переменные
- •Отложенные методы в Object Pascal
- •Полиморфные переменные
- •Отложенные методы в Objective-C
- •Полиморфные переменные
- •Отложенные методы в Smalltalk
- •Упражнения
- •Глава 15 Учебный пример: контейнерные классы
- •Упражнения
- •Глава 16 Пример: STL
- •Упражнения
- •Глава 17 Видимость и зависимость
- •Родственные экземпляры
- •Дружественные функции
- •Пространства имен
- •Постоянные члены
- •Упражнения
- •Глава 18 Среды и схемы разработки
- •18.1.1. Java API
- •Упражнения
- •19.5.Класс application
- •19.5.1.Класс button
- •Упражнения
- •Глава 20 Новый взгляд на классы
- •20.2.2.Класс Class
- •Упражнения
- •Глава 21 Реализация объектно-ориентированных языков
- •Литература для дальнейшего чтения
- •Упражнения
- •А.1. «Задача о восьми ферзях» на языке Apple Object Pascal
- •A.3. «Задача о восьми ферзях» на языке Java
- •A.3.1. HTML-файл для апплета Java
- •A.4. «Задача о восьми ферзях» на языке Objective-C
- •A.5. «Задача о восьми ферзях» на языке Smalltalk
- •Б.1. Версия без использования наследования
- •Б.2. Версия с использованием наследования
- •Глоссарий
converted to PDF by BoJIoc
непосредственно предшествующим родителем. То есть конструктор класса C может быть записан следующим образом:
C() : D(12), B(), A() { ... }
Конструкторы для виртуальных базовых классов должны вызываться первыми, то есть до конструкторов невиртуальных предков.
Виртуальные методы, определенные в виртуальных базовых классов, также могут быть источником проблем. Предположим, что каждый из четырех классов в листинге 13.5 обладает методом с именем initialize(). Он определен как виртуальный в классе Stream и переопределяется в каждом из последующих трех классов. Методы initialize() в классах
InStream и OutStream вызывают Stream::initialize() и, кроме того, выполняют некоторую специфическую для каждого из классов инициализацию.
Теперь рассмотрим метод initialize() для класса InOutStream. Он не может вызвать оба унаследованных метода InStream::initialize() и OutStream::initialize() без того, чтобы не вызвать дважды метод Stream::initialize(). Повторное обращение к методу Stream::initialize(), вероятно, будет иметь побочные эффекты. Способ из-бежать этой проблемы: переписать Stream::initialize() так, чтобы он определял, была ли уже осуществлена инициализация. Другой вариант: переопределить методы классов InStream и OutStream, чтобы они не вызывали метод класса Stream. В последнем случае класс InOutStream должен в явном виде обращаться к процедуре инициализации каждого из трех классов.
13.5. Множественное наследование в Java
Язык Java не поддерживает множественное наследование классов, но реализует множественное наследование интерфейсов. Класс может указать, что он поддерживает несколько различных интерфейсов. Например, один интерфейс может требовать запоминания данных на диске, а другой — определять протокол самоотображения объектов. Запоминаемый графический объект будет поддерживать оба эти интерфейса:
class graphicalObject implements Storable, Graphical
{
// ...
}
В то время как классы не могут наследовать от двух и более классов (расширяя их), интерфейсам это разрешено. Мы имеем право определить интерфейс для запоминаемых графических объектов следующим образом:
interface GraphicalObject extends Storable, Graphical
{
// ...
}
Литература для дальнейшего чтения
Критика множественного наследования встречается у Саккинена [Sakkinen 1988a]. Упомянутая работа является сокращенной адаптированной версией его Ph. D. диссертации [Sakkinen 1992]. Объяснение множественного наследования в языке C++
дается Эллис [Ellis 1990].
Упражнения
1.Приведите два примера множественного наследования в ситуациях, не связанных с компьютерами.
2.В работе [Wiener 1989] описан «практический пример множественного наследования в C++». Определен класс IntegerArray, который наследует от двух