C++primer学习:面向对象程序设计(5):再探文本查询程序

来源:互联网 发布:围墙设计图纸含数据 编辑:程序博客网 时间:2024/05/23 00:56

这一节初步探讨了如何设计一个继承类体系。

为我们前面所写的文本探测程序添加以下功能:

(1):可以将查询结果进行|,&,~的运算.运算的优先级按照C++规定的表达式来进行.如Query(“hair”)|Query(“bird”);

(2) : 添加一个历史系统,能够查询前面的进行的某个查询.并可以在其中增加内容并与其他查询组合.

(3):允许用户在查询的时候做出限制,从给定范围中挑出匹配的行显示.

这个体系的设计相对比较复杂,Textquery类负责进行基础的读入文件,Queryresult类负责保存结果.而我们重新定义一个继承体系Query_base继承体系,用Wordquery类,AndQuery类,OrQuery类负责保存信息.eval()函数负责解析结果,rep()函数负责打印查询的单词逻辑表达式.用Query类作为一个体系的接口类,掩盖整个体系,同时也减少用户操作难度.

同时对一些边界条件进行了检测,防止出错.

#ifndef Query_base_01#define Query_base_01#include "Textquery.h"#include "iterator"#include "memory"using namespace std;/************抽象基类query_base********************/class  Query;class Query_base{    friend Query& history_query(size_t n);    friend class Query;//通过该友元访问eval,rep函数public:    static vector<shared_ptr<Query>> history;private:      virtual   QueryResult eval(const Textquery&)const = 0;//纯虚函数      /******************重载这个虚函数,接受限制范围的行数******************/      virtual   QueryResult eval(const Textquery&,size_t,size_t)const;      virtual string rep()const = 0;protected:    Query_base() = default;};/***************重载eval*****************/QueryResult Query_base::eval(const Textquery& t, size_t min, size_t max)const{    auto res = eval(t);    auto dest = make_shared<set<size_t>>();    remove_copy_if(res.begin(), res.end(), inserter(*dest, (*dest).begin()),        [&](size_t q){  return (q<min || q>max); });    return QueryResult(rep(), res.get_file(), dest);}vector<shared_ptr<Query>>Query_base::history {shared_ptr<Query>()};/********定义一个接口类 Query,简化用户操作的复杂度,也可以减少类设计时的一些复杂度********/class Query{    friend Query operator~(const Query&);    friend Query operator&(const Query&, const Query&);    friend Query operator|(const Query&, const Query&);public:    /*******构造函数,接受一个string,返回一个wordquery的指针*************/    Query(const string& s);//创建一个新的Wordquery类,用来存储查找的单词    /**********覆盖eval的两种形式**************************/        QueryResult eval(const Textquery& t)const { return q->eval(t); };        QueryResult eval(const Textquery& t, size_t min, size_t max){        return q->eval(t, min, max);    }    /***************输出查询的单词*********************************/    virtual string rep()const { return q->rep(); };    /*************历史查询系统,返回前面第n次的查询结果**************************/    /************************添加记录****************************************************/    void add_history()const{        shared_ptr<Query> p = make_shared<Query>(*this);        q->history.push_back(p);    }private:    /**************私有构造函数,接受指向其他Query_base的智能指针,用于运算符&|~*************/    Query(shared_ptr<Query_base> p) :q(p){}    shared_ptr<Query_base> q;   //指向各个继承类};/*********************历史查询************/Query& history_query(size_t n){    size_t len = Query_base::history.size();    if (!(Query_base::history.empty()) && n>0 && n <= len)//history不为空&&n是有效的        return *(Query_base::history[len - n]);    else        throw::out_of_range("invaild n or empty history");}/*******************Wordquery类**************************/class Wordquery :public Query_base{    friend class Query;    /*************该构造函数自动调用Query_Base(),虽然没有可初始化的******************************/    Wordquery(const string& s) :query_word(s){}    /*************重新定义查询方式eval和查询的文本rep()*********************************/        QueryResult eval(const Textquery& t)const override{return t.query(query_word); };    /***************eval2直接继承************************************/        string rep()const override{ return query_word; };    string query_word;//查找的单词};/********定义Query构造函数函数********************/Query::Query(const string& s) :      q(make_shared<Wordquery>(Wordquery(s))){}/********定义Notquery*********************************************/class Notquery : public Query_base{    friend Query operator~(const Query&);    /*********构造函数********************/    Notquery(const Query&q) :query(q){}    /*************重新定义查询方式eval和查询的文本rep()*********************************/    QueryResult eval(const Textquery& t)const override;    string rep()const override { return "~("+ query.rep() + ")"; };    Query query;// q指向某个派生类};/****************重载operator~**********************/Query operator~(const Query&q){return shared_ptr<Query_base>(new Notquery(q));}QueryResult Notquery::eval(const Textquery& t)const{    auto result = query.eval(t);//通过Query运算对象进行虚调用    auto ret_lines = make_shared<set<size_t>>();    auto beg = result.begin(), end = result.end();    for (size_t n = 1; n != result.get_file()->size()+1; ++n)//遍历所有行号    {        if (beg == end || (*beg) != n)//n不在result里            ret_lines->insert(n);        else if (beg != end)// *beg == n            ++beg;    }    return QueryResult(rep(), result.get_file(), ret_lines);}/*****************定义BinaryQuery:抽象基类****************************/class BinaryQuery : public Query_base{protected:    BinaryQuery(const Query& lhs, const Query& rhs, string s) :    query1(lhs), query2(rhs), opsym(s){}    string opsym;//运算符号    Query query1, query2;//保存该对象构成的状态    /*************覆盖继承而来的虚函数***************************/    string rep()const override { return "( "+ query1.rep() +" "+ opsym+query2.rep()+" "+" )"; }; /**************不定义eval,因此它还是一个纯虚函数******************************/};/*************定义Addquery*********************/class Addquery :public BinaryQuery{    friend Query operator&(const Query&, const Query&);    /****************利用抽象基类的构造函数初始化类的对象**************************/    Addquery(const Query& lhs, const Query& rhs) :BinaryQuery(lhs, rhs, "&"){}    /****************覆盖相应的纯虚函数************************/    QueryResult eval(const Textquery&)const override;};/*************重载符号函数&************/Query operator&(const Query& lhs, const Query& rhs){    return shared_ptr<Query_base>(new Addquery(lhs, rhs));}QueryResult Addquery::eval(const Textquery& t)const{    auto  lhs_result = query1.eval(t), rhs_result = query2.eval(t);    auto ret_lines = make_shared<set<size_t>>();    set_intersection(lhs_result.begin(), lhs_result.end(), rhs_result.begin(),        rhs_result.end(), inserter(*ret_lines,ret_lines->begin()));    return   QueryResult(rep(), lhs_result.get_file(), ret_lines);}/*************定义Orquery*********************/class Orquery :public BinaryQuery{    friend Query operator|(const Query&, const Query&);    /****************利用抽象基类的构造函数初始化类的对象**************************/    Orquery(const Query& lhs, const Query& rhs) :BinaryQuery(lhs, rhs, "|"){}    /****************覆盖相应的纯虚函数************************/    QueryResult eval(const Textquery&)const override;};/*************重载符号函数|************/Query operator|(const Query& lhs, const Query& rhs){    return shared_ptr<Query_base>(new Orquery(lhs, rhs));}QueryResult Orquery::eval(const Textquery& t)const{    auto  lhs_result = query1.eval(t), rhs_result = query2.eval(t);    auto ret_lines = make_shared<set<size_t>>(lhs_result.begin(), lhs_result.end());    ret_lines->insert(rhs_result.begin(), rhs_result.end());    return   QueryResult(rep(), lhs_result.get_file(), ret_lines);}#endif#include "Query_base_derived.h"#include "iterator"#include "vector"using namespace std;int main(){    Textquery t("Text.txt");    auto q = Query("hair")|Query("bird");    q.add_history();    auto p = ~Query("fiery");    p.add_history();    auto q2 = history_query(2)&history_query(1);    print(cout, q2.eval(t,3,8));    return 0;}

这里写图片描述

0 0
原创粉丝点击