Проблему представления запроса мы решим, определив каждый операнд в классах AndQuery, NotQuery и OrQuery как указатель на тип Query*. Например:

class AndQuery {

public:

// ...

private:

Query *_lop;

Query *_rop;

};

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

_rop-eval();

На рис. 17.1 показана иерархия наследования, состоящая из абстрактного класса Query и четырех производных от него классов. Как этот рисунок транслируется в код программы на C++?

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++ (класс, функция, функция-член и т.д.)

<p>17.2. Идентификация членов иерархии</p>

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

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

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