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

17.4.1. Конструктор базового класса

В нашем базовом классе объявлено два нестатических члена: _solution и _loc:

class Query {

public:

// ...

protected:

set<short> *_solution;

vector<location> _loc;

// ...


};

Конструктор Query по умолчанию должен явно инициализировать только член _solution. Для инициализации _loc автоматически вызывается конструктор класса vector. Вот реализация нашего конструктора:

inline Query::Query(): _solution( 0 ) {}

В Query нам понадобится еще один конструктор, принимающий ссылку на вектор позиций:

inline

Query::

Query( const vector< locaton > &loc )

: _solution( 0 ), _loc( loc )


{}

Он вызывается только из конструктора NameQuery, когда объект этого класса используется для представления указанного в запросе слова. В таком случае передается предварительно подготовленный для него вектор позиций. Остальные три производных класса вычисляют свои векторы позиций в соответствующей функции-члене eval(). (В следующем подразделе мы покажем, как это делается. Реализации функций-членов eval() приведены в разделе 17.5.)

Какой уровень доступа обеспечить для конструкторов? Мы не хотим объявлять их открытыми, так как предполагается, что Query будет существовать в программе только в виде подобъекта в составе объектов производных от него классов. Поэтому мы объявим конструктор не открытым, а защищенным:

class Query {

public:

// ...

protected:

Query();

// ...


};

Ко второму конструктору класса Query предъявляются еще более жесткие требования: он не только должен конструировать Query в виде подобъекта производного класса, но этот производный класс должен к тому же быть NameQuery. Можно объявить конструктор закрытым, а NameQuery сделать другом класса Query. (В предыдущем разделе мы говорили, что производный класс может получить доступ только к открытым и защищенным членам базового. Поэтому любая попытка вызвать второй конструктор из классов AndQuery, OrQuery или NotQuery приведет к ошибке компиляции.)

class Query {

public:

// ...

protected:

Query();

// ...

private:

explicit Query( const vector<location>& );


};

(Необходимость второго конструктора спорна; вероятно, правильнее заполнить _loc в функции eval() класса NameQuery. Однако принятый подход в большей степени отвечает нашей цели проиллюстрировать использование конструктора базового класса.)

17.4.2. Конструктор производного класса

В классе NameQuery также определены два конструктора. Они объявлены открытыми, поскольку ожидается, что в приложении будут создаваться объекты этого класса:

class NameQuery : public Query {

public:

explicit NameQuery( const string& );

NameQuery( const string&, const vector<location>* );

// ...

protected:

// ...


};

Конструктор с одним параметром принимает в качестве аргумента строку. Она передается конструктору объекта типа string, который вызывается для инициализации члена _name. Конструктор по умолчанию базового класса Query вызывается неявно:

inline

NameQuery::

NameQuery( const string &name )

// Query::Query() вызывается неявно

: _name( name )


{}

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

inline

NameQuery::

NameQuery( const string &name, vector<location> *ploc )

: _name( name ), Query( *ploc )


{}

Конструкторы можно использовать так:

string title( "Alice" );

NameQuery *pname;

// проверим, встречается ли "Alice" в отображении слов

// если да, получить ассоциированный с ним вектор позиций

if ( vector<location> *ploc = retrieve_location( title ))

pname = new NameQuery( title, ploc );


else pname = new NameQuery( title );

В каждом из классов NotQuery, OrQuery и AndQuery определено по одному конструктору, каждый из которых вызывает конструктор базового класса неявно:

inline NotQuery::

NotQuery( Query *op = 0 ) : _op( op ) {}

inline OrQuery::

OrQuery( Query *lop = 0, Query *rop = 0 )

: _lop( lop ), _rop( rop )

{}

inline AndQuery::

AndQuery( Query *lop = 0, Query *rop = 0 )

: _lop( lop ), _rop( rop )


{}

(В разделе 17.7 мы построим объекты каждого из производных классов для представления различных запросов пользователя.)