C++primer学习:面象对象程序设计(5):容器与继承
2015-10-29 18:57
357 查看
我们不能在容器中保存不同类型的元素.即使它们是具有继承关系的类体系.一般来说,直接保存对象会导致派生类中的基类部分被忽略.所以我们通常采取用指针来保存对象。一般用智能指针进行保存.
[练习]:定义一个存放Quote对象的vector和存放指针的vector来比较两者的不同.
vector<shared_ptr<Quote>> baseket1; vector<Quote> baseket2; bulk_quote y1("0-1",5,10,0.2),y2("0-2",5,10,0.3); baseket1.push_back(make_shared<bulk_quote>(y1)); baseket1.push_back(make_shared<bulk_quote>(y2)); baseket2.push_back(y1); baseket2.push_back(y2); /**************************************************/ double sum_price = 0; for (auto price: baseket1) sum_price += price->net_price(100); cout << sum_price<<endl; /**************************************************/ sum_price = 0; for (auto price : baseket2) sum_price += price.net_price(100); cout << sum_price; return 0; }
======================================================================================
[练习]:使用指针会增加编程的复杂度,所以我们需要编写一个自己的容器用来管理Quote类.接受Quote类型的参数而不是相应的智能指针.
note[1]:用来存储智能指针的关联容器需要一个比较函数来进行排序,因为保存的书籍可能是同一种书,因此需要用multiset来保存.这样在进行输出售价的时候就非常方便,因为相同的书籍总是在相邻的.
note[2]:为了提高效率,避免不必要的拷贝,我们可以将Basket的成员函数push_back()重载为拷贝版本和移动版本,在接受临时变量的时候只需要接管内存即可.注意在push_back里面我们需要获得一个智能指针,但是智能指针指向的内存如何分配呢?使用make_shared构造内存就遇到了不知道具体动态类型的问题.所以需要把这个任务交给Quote类体系,只有它们才知道自己的具体类型.因此需要定义一个虚函数clone(),进行动态绑定,用来拷贝或者移动真正的对象.在clone()里面动态分配内存.//注意clone()里面也应该分为移动来获得内存或者拷贝获得内存.
note[3]:由于vs2013不支持引用限定,所以我在clone()中添加了一个参数int n,用来区分是拷贝版本还是移动版本.
note[4]:在multiset的比较函数方面有一些地方要注意.(1)必须定义为static,这样函数其实是一个全局变量,或者干脆不定义为成员函数.否则普通成员函数是有一个隐藏形参this指针的,这样的话在传递函数用来初始化multiset的时候就会出错,因为隐藏形参并不会被传递过去.
note[5]:注意在处理总的数据时,我们用到了uppper_bound,它实际上是由比较函数确定如何选择返回值的,假如我们的比较函数是以price作为比较的依据,那么upper_bound就会跳过相同的price.
/********virtual clone,拷贝自己的对象并返回一个动态指针,用于分配内存时动态绑定*********/ virtual Quote* clone() const { return new Quote(*this); } /********virtual clone,移动自己的对象并返回一个动态指针,用于分配内存时动态绑定*********/ virtual Quote* clone(int n) const { return new Quote(std::move(*this)); } /********virtual clone,拷贝自己的对象并返回一个动态指针,用于分配内存时动态绑定*********/ bulk_quote* clone()const override { return new bulk_quote(*this); } /********virtual clone,移动自己的对象并返回一个动态指针,用于分配内存时动态绑定*********/ bulk_quote* clone(int n)const override{ return new bulk_quote(std::move(*this)); } /********virtual clone,拷贝自己的对象并返回一个动态指针,用于分配内存时动态绑定*********/ limit_quote* clone() const override { return new limit_quote(*this); } /********virtual clone,移动自己的对象并返回一个动态指针,用于分配内存时动态绑定*********/ limit_quote* clone(int n) const override { return new limit_quote(std::move(*this)); }
/********************Basket************************************/ class Basket { public: /**************用来增加智能指针 拷贝版本和移动版本**********************/ void push_back(const Quote& sale){ items.insert(shared_ptr<Quote>(sale.clone())); } void push_back(Quote&& sale) {items.insert(shared_ptr<Quote>(sale.clone(0))) ; } void total_receipt(ostream&)const; private: /*****************私有比较函数,用于multiset排序********************************/ /***************** 一定要声明为static!!!!,这样不含this指针,函数类型不会出错******************/ static bool compare(const shared_ptr<Quote>& b1, const shared_ptr<Quote>& b2){ return b1->isbn() < b2->isbn(); } /******************* 存放智能指针*************************************/ multiset<shared_ptr<Quote>,decltype(compare)*> items{ compare }; }; //打印所有信息 void Basket::total_receipt(ostream& os)const { double sum = 0; for (auto beg = items.begin(); beg != items.end(); beg = items.upper_bound(*beg)) sum +=print_total(os, **beg, items.count(*beg)); cout << "\ntotal_fees: " << sum; }
相关文章推荐
- C++学习笔记
- 01背包问题,dp和贪心解法(c++11)
- 1029c语言文法
- thoughtworks家庭作业C++版本
- 字符匹配
- C语言:字符数组的内容为;tneduts a ma i;,内容改为i am a student.只能开辟有限个空间
- c语言文法
- C语言:day12~通讯录
- 1029 C语言文法
- 1014 C语言文法定义与C程序的推导过程
- C语言文法定义及C程序的推导过程
- c++ 友元函数
- C语言文法定义与C程序的推导过程
- C语言:Day10~Day11
- 1029 C语言文法
- C语言:day9~指针
- C语言文法
- C语言:Day7~Day8
- VC++ MFC获取对话框上控件的位置
- 1014 我的C语言文法定义与C程序推导过程