Следует заметить то, что вызов функции rep()
объекта класса NotQuery
в конечном счете приводит к виртуальному вызову функции собственной функции-члена rep()
: query.rep()
— это невиртуальный вызов функции-члена rep()
класса Query
. Функция Query::rep()
в свою очередь осуществляет вызов q->rep()
, являющийся виртуальным вызовом через указатель Query_base
.
Оператор ~
динамически резервирует новый объект класса NotQuery
. Оператор return
(неявно) использует конструктор Query()
, получающий указатель shared_ptr
. Таким образом, оператор return
эквивалентен следующему:
//
//
shared_ptr
return Query(tmp); //
//
Функция-член eval()
достаточно сложна, поэтому реализуем ее вне тела класса. Более подробно функция eval()
рассматривается в разделе 15.9.4.
BinaryQuery
Класс BinaryQuery
— это абстрактный базовый класс, содержащий данные, необходимые двум классам запроса, AndQuery
и OrQuery
, которые используют по два операнда:
class BinaryQuery: public Query_base {
protected:
BinaryQuery(const Query &l, const Query &r, std::string s):
lhs(l), rhs(r), opSym(s) { }
//
std::string rep() const { return "(" + lhs.rep() + " "
+ opSym + " "
+ rhs.rep() + ")"; }
Query lhs, rhs; //
std::string opSym; //
};
Данными класса BinaryQuery
являются два операнда запроса и символ оператора. Конструктор получает эти два операнда и символ оператора, каждый из которых он хранит в соответствующих переменных-членах.
Чтобы отобразить объект класса BinaryOperator
, следует вывести выражение в скобках, состоящее из левого операнда, оператора и правого операнда. Как и в случае класса NotQuery
, вызов функции rep()
в конечном счете осуществляет вызов виртуальных функций rep()
объектов класса Query_base
, на которые указывают параметры lhs
и rhs
.
BinaryQuery
не переопределяет функцию eval()
, а следовательно, наследует ее чистой виртуальной. Таким образом, класс BinaryQuery
остается абстрактным и его объекты создавать нельзя.
AndQuery
, OrQuery
и их операторыКлассы AndQuery
и OrQuery
, а также соответствующие им операторы очень похожи:
class AndQuery: public BinaryQuery {
friend Query operators(const Query&, const Query&);
AndQuery(const Query &left, const Query &right):
BinaryQuery(left, right, "&") { }
//
//
QueryResult eval(const TextQuery&) const;
};
inline Query operator&(const Query &lhs, const Query &rhs) {
return std::shared_ptr
}
class OrQuery: public BinaryQuery {
friend Query operator|(const Query&, const Query&);
OrQuery(const Query &left, const Query &right):
BinaryQuery(left, right, "|") { }
QueryResult eval(const TextQuery&) const;
};
inline Query operator|(const Query &lhs, const Query &rhs) {
return std::shared_ptr
}
Эти классы объявляют соответствующий оператор дружественным и определяют конструктор, создающий их базовую часть класса BinaryQuery
с соответствующим оператором. Они наследуют определение функции rep()
от класса BinaryQuery
, но каждый из них определяет собственную версию функции eval()
.