首页 > 代码库 > Chapter15:程序实例
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) const10 {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 Quote38 {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 Quote44 {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) const50 {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 else57 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) const107 {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) const117 {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 }
Chapter15:程序实例
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。