您的位置:首页 > 编程语言 > C语言/C++

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: