C++primer学习:面象对象程序设计(5):容器与继承

本文探讨了在C++中使用智能指针管理不同类型的Quote对象,并介绍了一种自定义容器Basket的设计方法,该容器能够高效地存储和管理这些对象。

我们不能在容器中保存不同类型的元素.即使它们是具有继承关系的类体系.一般来说,直接保存对象会导致派生类中的基类部分被忽略.所以我们通常采取用指针来保存对象。一般用智能指针进行保存.

[练习]:定义一个存放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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值