Query_base类和Query类
//这是一个抽象基类,具体的查询类型从中派生,所有成员都是private的
class Query_base {
friend class Query;
protected:
using line_no = TextQuery::line_no;//用于level函数
virtual ~Query_base() = default;
private:
//eval返回与当前Query匹配的QueryResult
virtual QueryResult eval(const TextQuery&) const = 0;
//rep是表示查询 的一个string
virtual std::string rep() const = 0;
};
//这是一个管理Query_base继承体系的接口类
class Query{
//这些运算符需要访问接受shared_ptr的构造函数,而该函数是私有的
friend Query operator~(const Query &);
friend Query operator|(const Query&,const Query&);
friend Query operator&(const Query&,const Query&);
public:
Query(const std::string&);//构建一个新的WordQuery
//接口函数:调用对应的Query_base操作
QueryResult eval(const TextQuery &t) const
{return q->eval(t);}
std::string rep() const {return q->req();}
private:
Query(std::shared_ptr<Query_base> query):q(query){ }
std::shared_ptr<Query_base> q;
};
Query的输出运算符
std::ostream &
operator<<(std::ostream &os,const Query &query)
{
//Query::rep通过它的Query_base指针对rep()进行虚调用
return os<<query.rep();
}
Query andq = Query(sought1) & Query(sought2);
cout<<andq<<endl;
派生类
class WordQuery: public Query_base {
friend class Query; //Query使用WordQuery构造函数
WordQuery(const std::string &s) : query_word(s) { }
//具体的类:WordQuery将定义所有继承而来的纯虚函数
QueryResult eval(const TextQuery &t) const
{return t.query(query_word);}
std::string rep() const {return query_word;}
std::string query_word; //要查找的单词
};
NotQuery类及 ~运算符
class NotQuery : public Query_base {
friend Query operator~(const Query &);
NotQuery(const Query &q):query(q){ }
//具体的类:NotQuery将定义所有继承而来的纯虚函数
std::string rep() const {return "~(" + query.rep() + ")";}
QueryResult eval(const TextQuery&) const;
Query query;
};
inline Query operator~(const Query &operand)
{
return std::shared_ptr<Query_base>(new NotQuery(oprand));
}
//分配一个新的NotQuery对象
//将所得的NotQuery指针绑定到一个shared_ptr<Query_base>
shared_ptr<Query_base> tmp(new NotQuery(expr));
return Query(tmp); //使用接受一个shared_ptr的Query构造函数
BinaryQuery类
class BinaryQuery : public Query_base{
protected:
BinaryQuery(const Query &l,const Query &r,std::string s):
lhs(l),rhs(r),opSym(s){ }
//抽象类:BinaryQuery不定义eval
std::string rep() const { return "(" + lhs.rep() + " "
+opSym + ""
+rhs.rep() + ")";}
Query lhs,rhs; //左侧和右侧运算符对象
std::string opSym; //运算符名字
};
AndQuery类、OrQuery类及相应的运算符
class AndQuery : public BinaryQuery {
friend Query operator&(const Query&,const Query&);
AndQuery(const Query &left,const Query &right) :
BinaryQuery(left,right,"&"){ }
//具体的类: AndQuery继承了rep并且定义了其他纯虚函数
QueryResult eval(const TextQuery&) const;
};
inline Query operator&(const Query &lhs,const Query &rhs)
{
return std::shared_ptr<Query_base>(new AndQuery(lhs,rhs));
}
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<Query_base>(new OrQuery(lhs,rhs));
}
eval函数
//返回运算对象查询结果set的并集
OrQuery::eval(const TextQuery& text) const
{
//通过Query成员lhs和rhs进行的虚调用
//调用eval返回每个运算对象的QueryResult
auto right = rhs.eval(text),left = lhs.eval(text);
//将左侧运算对象的行号拷贝到结果set中
auto ret_lines =
make_shared<set<line_no>>(left.begin(),left.end());
//插入右侧运算对象所得的行号
ret_lines->insert(right.begin(),right.end());
//返回一个新的QueryResult,它表示lhs和rhs的并集
return QueryResult(rep(),ret_lines,left.get_file());
}
//返回运算对象查询结果set的交集
QueryResult
AndQuery::eval(const TextQuery& text) const
{
//通过Query运算对象进行的虚调用,以获得运算对象的查询结果set
auto left = lhs.eval(text),right = rhs.eval(text);
//保存left 和 right交集的set
auto ret_lines = make_shared<set<line_no>>();
//将两个范围的交集写入一个目的迭代器中
//本次调用的目的迭代器向ret添加元素
set_intersection(left.begin(),left.end(),
right.begin(),right.end(),
inserter(*ret_lines,ret_lines->begin()));
return QueryResult(rep(),ret_lines,left.get_file());
}
//返回运算对象的结果set中不存在的行
QueryResult
NotQuery::eval(const TextQuery& text) const
{
//通过Query运算对象对eval进行虚调用
auto result = query.eval(text);
//开始时结果set为空
auto ret_lines = make_shared<set<line_no>>();
//我们必须在运算对象出现的所有行中进行迭代
auto beg = result.begin(),end = result.end();
//对于输入文件的每一行,如果该行不在result当中,则将其添加到ret_lines
auto sz = result.get_file()->size();
for(size_t n = 0;n != sz; ++n){
//如果我们还没有处理完result的所有行
//检查当前行是否存在
if(beg = end || *beg != n)
ret_lines->insert(n); //如果不在result当中,添加这一行
else if(beg != end)
++beg; //否则继续获取result的下一行(如果有的话)
}
return QueryResult(rep(),ret_lines,result.get_file());
}
文章来源地址https://www.toymoban.com/news/detail-620382.html
文章来源:https://www.toymoban.com/news/detail-620382.html
到了这里,关于c++ 派生类 文本查询程序再探的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!