Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Липпман.doc
Скачиваний:
7
Добавлен:
14.08.2019
Размер:
7.54 Mб
Скачать

17.2.3. Резюме

Открытый интерфейс каждого из четырех производных классов состоит из их открытых членов и унаследованных открытых членов Query. Когда мы пишем:

Query *pq = new NmaeQuery( "Monet" );

то получить доступ к открытому интерфейсу Query можно только через pq. А если пишем:

pq->eval();

то вызывается реализация виртуальной eval() из производного класса, на объект которого указывает pq, в данном случае – из класса NameQuery. Строкой

pq->display();

всегда вызывается невиртуальная функция display() из Query. Однако она выводит разрешающее множество строк объекта того производного класса, на который указывает pq. В этом случае мы не стали полагаться на механизм виртуализации, а вынесли разделяемую операцию и необходимые для нее данные в общий абстрактный базовый класс Query. display() – это пример полиморфного программирования, которое поддерживается не виртуальностью, а исключительно с помощью наследования. Вот ее реализация (это пока только промежуточное решение, как мы увидим в последнем разделе):

void

Query::

display()

{

if ( ! _solution->size() ) {

cout << "\n\tИзвините, "

<< " подходящих строк в тексте не найдено.\n"

<< endl;

}

set<short>::const_iterator

it = _solution->begin(),

end_it = _solution->end();

for ( ; it != end_it; ++it ) {

int line = *it;

// не будем пользоваться нумерацией строк с 0...

cout << "(" << line+1 << " ) "

<< (*_text_file)[line] << '\n';

}

cout << endl;


}

В этом разделе мы попытались определить иерархию классов Query. Однако вопрос о том, как же построить с ее помощью структуру данных, описывающую запрос пользователя, остался без ответа. Когда мы приступим к реализации, это определение придется пересмотреть и расширить. Но прежде нам предстоит более детально изучить механизм наследования в языке C++.

Упражнение 17.3

Рассмотрите приведенные члены иерархии классов для поддержки библиотеки из упражнения 17.1 (раздел 17.1). Выявите возможные кандидаты на роль виртуальных функций, а также те члены, которые являются общими для всех предметов, выдаваемых библиотекой, и, следовательно, могут быть представлены в базовом классе. (Примечание: LibMember – это абстракция человека, которому разрешено брать из библиотеки различные предметы; Date – класс, представляющий календарную дату.)

class Library {

public:

bool check_out( LibMember* ); // выдать

bool check_in ( LibMember* ); // принять назад

bool is_late( const Date& today ); // просрочил

double apply_fine(); // наложить штраф

ostream& print( ostream&=cout );

Date* due_date() const; // ожидаемая дата возврата

Date* date_borrowed() const; // дата выдачи

string title() const; // название

const LibMember* member() const; // записавшийся


};

Упражнение 17.4

Идентифицируйте члены базового и производных классов для той иерархии, которую вы выбрали в упражнении 17.2 (раздел 17.1). Задайте виртуальные функции, а также открытые и защищенные члены.

Упражнение 17.5

Какие из следующих объявлений неправильны:

class base { ... };

(a) class Derived : public Derived { ... };

(b) class Derived : Base { ... };

(c) class Derived : private Base { ... };

(d) class Derived : public Base;


(e) class Derived inherits Base { ... };