• Chapter15:程序实例


    购物篮程序:模拟虚拷贝

     1 class Basket
     2 {
     3 public:
     4     //使用合成的默认构造函数和拷贝控制
     5     void add_item(const shared_ptr<Quote> &sale)
     6     {
     7         items.insert(sale);
     8     }
     9     double total_recipt(ostream& os) const
    10     {
    11         double sum = 0.0;
    12         for (auto iter = items.cbegin(); iter != items.cend(); iter = items.upper_bound(*iter))
    13         {
    14             sum += print_total(os, **iter, items.count(*iter));
    15         }
    16     }
    17 private:
    18     static bool compare(shared_ptr<Quote> &lhs, shared_ptr<Quote> &rhs)
    19     {
    20         return lhs->isbn() < rhs.isbn();
    21     }
    22     multiset<shared_ptr<Quote>, decltype(compare)*> items{ compare };
    23 
    24 };
    25 
    26 //使用方法
    27 Basket bsk;
    28 bsk.add_item(make_shared<Quote>("123", 45));
    29 bsk.add_item(make_shared<Bulk_quote>("345", 45,3,15));
    30 
    31 //我们想这么使用,即:add_item负责内存的分配与管理
    32 bsk.add_item(Quote("123", 45));
    33 bsk.add_item(Bulk_quote("345", 45, 3, 15));
    34 
    35 //问题是,我们无法通过参数的类型Quote,来得知应该分配什么样的内存,Quote or Bulk_quote?
    36 //解决方法:模拟虚拷贝
    37 class Quote
    38 {
    39 public:
    40     virtual Quote* clone() const & { return new Quote(*this); }
    41     virtual Quote* clone() && {return new Quote(std::move(*this)); }
    42 };
    43 class Bulk_quote:public Quote
    44 {
    45 public:
    46     virtual Bulk_quote* clone() const & { return new Bulk_quote(*this); }
    47     virtual Bulk_quote* clone() && {return new Bulk_quote(std::move(*this)); }
    48 };
    49 
    50 void add_item(const Quote &sale)
    51 {
    52     items.insert(shared_ptr<Quote>(sale.clone()));
    53 }
    54 void add_item(Quote &&sale)
    55 {
    56     items.insert(shared_ptr<Quote>(std::move(sale).clone()));
    57 }

    文本查询程序(2):允许单词的逻辑组合查询如:fiery&bird|wind

    分析:

    我们只需要对于TextQuery,定义operator~(),operator|(TextQuery1,TextQuery2),operator&(TextQuery1,TextQuery2)即可完成任务。

    我们这样使用:TextQuery(fiery)&TextQuery(brid)|TextQuery(wind),会出现三个TextQuery对象。

    逻辑上来讲,文本文档对象TextQuery只需要一个。其实,真正需要多个操作的是查询这一操作。我们现在有必要将查询这一操作分离出来。

    之前的查询是一个函数[参见 Chapter12&Chapter13程序实例]:

    47 //如果没有找到string,应该返回什么?
    48 //我们定义一个局部static对象,它指向一个空行号set的shared_ptr,未找到单词,则返回此对象的一个拷贝
    49 QueryResult TextQuery::query(const string &sought) const
    50 {
    51     static shared_ptr<set<line_no>> nodata(new set<line_no>);
    52     //不使用下标运算符来查找,避免将单词添加到wm中
    53     auto loc = wm.find(sought);
    54     if (loc == wm.end())
    55         return { sought, nodata, file };
    56     else
    57         return { sought, loc->second, file };
    58 }

    现在我们把它分离出来,重新写作一个类Query,然后定义operator~,operator|,operator&即可。

    但是书中为了演示继承,所以把操作设计成继承体系。

    每个查询类只包含两个操作:

    eval,接受一个TextQuery对象,返回一个QueryResult;

    rep,返回基础查询的string表示形式。

    具体的类设计细节参见书本。

    然后使用Query类隐藏继承体系。

    所以Query_base的所有函数都是私有的。(私有虚函数竟然可以被派生基类访问?Query不是NotQuery的友元,亦可以调用私有虚函数??

      1 class Query_base
      2 {
      3     friend class Query;
      4 protected:
      5     using line_no = TextQuery::line_no;
      6     virtual ~Query_base() = default;
      7 private:
      8     virtual QueryResult eval(const TextQuery&) const = 0;
      9     virtual string rep() const = 0;
     10 };
     11 
     12 class Query
     13 {
     14     friend Query operator~(const Query&);
     15     friend Query operator|(const Query&, const Query&);
     16     friend Query operator&(const Query&, const Query&);
     17 public:
     18     Query(const string&);//要生成WordQuery,WordQuery定义之后再定义;
     19     QueryResult eval(const TextQuery &t) const { return q->eval(t); }
     20     string rep() const { return q->rep(); }
     21 private:
     22     Query(shared_ptr<Query_base> query) :q(query) {}
     23     shared_ptr<Query_base> q;
     24 };
     25 
     26 ostream& operator<<(ostream &os, const Query &query)
     27 {
     28     return os << query.rep();
     29 }
     30 
     31 
     32 //Query_base的继承体系
     33 class WordQuery :public Query_base
     34 {
     35     friend class Query;
     36     WordQuery(const string& s) :query_word(s) {}
     37     QueryResult eval(const TextQuery &t) const { return t.query(query_word); }
     38     string rep() const { return query_word; }
     39     string query_word;
     40 };
     41 //注意,Query只是Query_base和WordQuery的友元
     42 inline Query::Query(const string &s)
     43     :q(new WordQuery(s)) {}
     44 
     45 
     46 class NotQuery :public Query_base
     47 {
     48     friend Query operator~(const Query&);
     49     NotQuery(const Query& q):query(q){}
     50     string rep()const { return "~(" + query.rep() + ")"; }
     51     QueryResult eval(const TextQuery&) const;
     52     Query query;
     53 };
     54 
     55 inline Query operator~(const Query &oprand)
     56 {
     57     return shared_ptr<Query_base>(new NotQuery(oprand));
     58 }
     59 
     60 class BinaryQuery :public Query_base
     61 {
     62     //抽象基类,Query不访问,故不用friend
     63 protected:
     64     BinaryQuery(const Query &l, const Query &r, string s)
     65         :lhs(l), rhs(r), opSym(s) {}
     66     string rep() const { return "(" + lhs.rep() + " " + opSym + " " + rhs.rep() + ")"; }
     67     Query lhs, rhs;
     68     string opSym;
     69 };
     70 
     71 class AndQuery :public BinaryQuery
     72 {
     73     friend Query operator&(const Query&, const Query&);
     74     AndQuery(const Query &left, const Query &right)
     75         :BinaryQuery(left, right, "&") {}
     76     QueryResult eval(const TextQuery&) const;
     77 };
     78 
     79 inline Query operator&(const Query &lhs, const Query &rhs)
     80 {
     81     return shared_ptr<Query_base>(new AndQuery(lhs, rhs));
     82 }
     83 
     84 class OrQuery :public BinaryQuery
     85 {
     86     friend Query operator|(const Query&, const Query&);
     87     OrQuery(const Query &left, const Query &right)
     88         :BinaryQuery(left, right, "|") {}
     89     QueryResult eval(const TextQuery&) const;
     90 };
     91 
     92 inline Query operator|(const Query &lhs, const Query &rhs)
     93 {
     94     return shared_ptr<Query_base>(new OrQuery(lhs, rhs));
     95 }
     96 
     97 QueryResult OrQuery::eval(const TextQuery &text) const
     98 {
     99     auto right = rhs.eval(text), left = lhs.eval(text);
    100 
    101     auto ret_lines = make_shared<set<line_no>>(left.begin(), left.end());
    102     ret_lines->insert(right.begin(), right.end());
    103     return QueryResult(rep(), ret_lines, left.get_file());
    104 }
    105 
    106 QueryResult AndQuery::eval(const TextQuery &text) const
    107 {
    108     auto right = rhs.eval(text), left = lhs.eval(text);
    109 
    110     auto ret_lines = make_shared<set<line_no>>();
    111     set_intersection(left.begin(), left.end(), right.begin(), right.end(),inserter(*ret_lines,ret)lines->begin()));
    112     return QueryResult(rep(), ret_lines, left.get_file());
    113 
    114 }
    115 
    116 QueryResult NotQuery::eval(const TextQuery &text) const
    117 {
    118     auto result = query.eval(text);
    119     auto ret_lines = make_shared<set<line_no>>();
    120     auto beg = result.begin(), end = result, end();
    121     auto sz = result.get_file()->size();
    122     for (size_t n = 0; n != sz; ++n)
    123     {
    124         if (beg == end || *beg != n)
    125             ret_lines->insert(n);
    126         else if (beg != end)
    127             ++beg;
    128     }
    129 
    130     return QueryResult(rep(), ret_lines, result.get_file());
    131 }
  • 相关阅读:
    《当程序员的那些狗日日子》(五十五)另一种生存之道
    "泄密"之秘 互联网最大规模用户资料泄露事件真相
    《当程序员的那些狗日日子》(五十九)凤凰涅磐
    《当程序员的那些狗日日子》(五十七)迟来的爱恋
    《当程序员的那些狗日日子》(六十)大海作证
    PHP开发者常犯的10个MySQL错误
    《当程序员的那些狗日日子》(五十八)盼望已久的收获
    Javascript 面向对象编程
    图片搜索引擎图像识别匹配的原理(二)
    如何做到 jQueryfree?
  • 原文地址:https://www.cnblogs.com/wangyanphp/p/5853902.html
Copyright © 2020-2023  润新知