Следует заметить то, что вызов функции 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().