Query
AndQuery OrQuery NotQuery NameQuery
Рис. 17.1. Иерархия классов Query
В разделе 2.4 мы рассматривали реализацию иерархии классов IntArray. Синтаксическая структура определения иерархии, изображенной на рис. 17.1, аналогична:
class Query { ... };
class AndQuery : public Query { ... };
class OrQuery : public Query { ... };
class NotQuery : public Query { ... };
class NameQuery : public Query { ... };
Наследование задается с помощью списка базовых классов. В случае одиночного наследования этот список имеет вид:
: уровень-доступа базовый-класс
где уровень-доступа – это одно из ключевых слов public, protected, private (смысл защищенного и закрытого наследования мы обсудим в разделе 18.3), а базовый-класс – имя ранее определенного класса. Например, Query является открытым базовым классом для любого из четырех классов запросов.
Класс, встречающийся в списке базовых, должен быть предварительно определен. Следующего опережающего объявления Query недостаточно для того, чтобы он мог выступать в роли базового:
// ошибка: Query должен быть определен
class Query;
class NameQuery : piblic Query { ... };
Опережающее объявление производного класса должно включать только его имя, но не список базовых классов. Поэтому следующее опережающее объявление класса NameQuery приводит к ошибке компиляции:
// ошибка: опережающее объявление не должно
// включать списка базовых классов
class NameQuery : public Query;
Правильный вариант в данном случае выглядит так:
// опережающее объявление как производного,
// так и обычного класса содержит только имя класса
class Query;
class NameQuery;
Главное различие между базовыми классами Query и IntArray (см. раздел 2.4) состоит в том, что Query не представляет никакого реального объекта в нашем приложении. Пользователи класса IntArray вполне могут определять и использовать объекты этого типа непосредственно. Что же касается Query, то разрешается определять лишь указатели и ссылки на него, используя их для косвенного манипулирования объектами производных классов. О Query говорят, что это абстрактный базовый класс. В противоположность этому IntArray является конкретным базовым классом. Преобладающей формой в объектно-ориентированном проектировании является определение абстрактного базового класса типа Query и одиночное открытое наследование ему.
Упражнение 17.1
Библиотека может выдавать на руки предметы, для каждого из которых определены специальные правила выдачи и возврата. Организуйте их в иерархию наследования:
книга аудио-книга
аудиокассета детская кукла
видеокассета видеоигра для приставки SEGA
книга с подневной оплатой видеоигра для приставки SONY
книга на компакт-диске видеоигра для приставки Nintendo
Упражнение 17.2
Выберите или придумайте собственную абстракцию, содержащую семейство типов. Организуйте типы в иерархию наследования:
(a) Форматы графических файлов (gif, tiff, jpeg, bmp и т.д.)
(b) Геометрические примитивы (прямоугольник, круг, сфера, конус и т.д.)
(c) Типы языка C++ (класс, функция, функция-член и т.д.)