- •Введение
- •Как получить исходные тексты
- •Что требуется знать для чтения книги
- •Предисловие к первому изданию
- •Благодарности
- •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
}
Заметьте, что метод next не описан как виртуальный: нельзя изменить тип возвращаемого значения виртуальной функции. Важно помнить, что в языке C++ это приведение типа будет законным только для указателей, а не для собственно объектов (см. упражнение 2 этой главы). Функция dynamic_cast является частью системы RTTI (Run-Time Typing Information — идентификация типа во время выполнения), которая была описана в
главе 10. Приведение типов через RTTI должно использоваться вместо более ранних синтаксических форм, поскольку неправильное приведение типов данных является стандартным источником ошибок в программах.
В языке Object Pascal задействована аналогичная идея. Поскольку объекты рассматриваются внутренним образом как указатели, то это преобразование может применяться к объектам любого типа, а не только к указателям. Язык Object Pascal обеспечивает проверку класса объекта во время выполнения, так что все «сомнительные» приведения типа должны быть выявлены с помощью явной проверки до присваивания.
var
x : TextWindow; y : Window;
begin
...
if Member(y, TextWindow) then x := TextWindow(y)
else writeln('illegal window assignment');
...
end;
В языке Java переменная, которая содержит значение, принадлежащее подклассу приписанного ей класса, может быть приведена к типу подкласса. Однако такие преобразования проверяются во время выполнения программы, и если результат неправилен, то возбуждается исключительная ситуация. Если программист ее не желает, тип значения должен проверяться с помощью оператора instanceOf, как это делается в следующем примере:
Ball aBall; WhiteBall wBall;
if (aBall instanceOf WhiteBall) wBall = (WhiteBall) aBall;
else
...
Упражнения
1. Объясните, почему в языках со статическими типами данных (вроде C++ и Object Pascal) нельзя присваивать значение типа надкласса переменной, описанной как экземпляр подкласса. То есть команды вроде нижеследующих приводят к сообщению компилятора об ошибке:
2. |
TextWindow X; |
3. |
Window Y; |
4. |
... |
|
X := Y; |
5. Предположим, что в C++ метод распределения памяти работает так, как описано в разделе 12.1. Объясните, какие могут возникнуть проблемы, если пользователь пытается обойти ограничение, описанное в упражнении 1, путем приведения типов данных,
используя команду присваивания вроде
x = (TextWindow) Y;