C++Primer_Chap15_面向对象程序设计_List08_容器和继承_笔记

  当我们使用容器存放继承体系中的对象时,通常必须采用间接存储的方式。因为不允许在容器中保存不同类型的元素,所以不能把具有继承关系的多种类型的对象之间存放在容器中。

在容器中放置(智能)指针而非对象

vector<shared_ptr<Quote>> basket;

basket.push_back( make_shared<Quote>("0-201-82470-1", 50));
basket.push_back( make_shared<Bulk_quote>("0-201-82470-1", 50, 10, 0.25));

//调用Quote定义的版本;打印562.5,即在15*50*(1-0.25)
cout << basket.back()->net_price(15) << endl;

编写Basket类

  对于C++面向对象的变成来说,一个悖论是我们无法直接使用对象进行面向对象变成。相反,我们必须使用指针和引用。因为指针会增加程序的复杂性,所以我们经常定义一些辅助的类来处理这种复杂的情况:

class Basket {
public:
    //Basket使用合成的默认构造函数和拷贝控制成员
    void add_item( const std::shared_ptr<Quote> &sale)
        { items.insert(sale);}
    //打印每本书的总价和购物篮中所有书的总价
    double total_receipt( std::ostream&) const;
private:
    //该函数用于比较shared_ptr,multiset成员会用到它
    static bool compare( const std::shared_ptr<Quote> &lhs,
                            const std::shared_ptr<Quote> &rhs)
        { return lhs.isbn() < rhs->isbn();}
    //multiset保存多个报价,按照compare成员排序
    std::multiset<std::shared_ptr<Quote>, decltype(compare)*> items(compare);
};

double Basket::total_receipt( ostream &os) const
{
    double sum =0.0;
    for( auto iter = items.cbegin(); iter != items.cend();
         iter = items.upper_bound(*iter))
    {
    sum += print_total(os, **iter, items.count(*iter));
    }
    os << "Total Sale:" << sum << endl;
    return sum;
}

隐藏指针

  Basket的用户必须处理动态内存,因为add_item需要接受一个shared_ptr参数。

Basket bsk;
bsk.add_item(make_shared<Quote>("123", 45));
bsk.add_item(make_shared<Bulk_quote>("345", 45, 3, 0.15));

  下一步重新定义add_item,使其接受一个Quote对象而非shared_ptr。新版本的add_item将负责处理内存分配:

void add_item( const Quote& sale);
void add_item( Quote&& sale);

  为了防止Bulk_quote对象在该函数使用时被迫切掉一部分

模拟虚拷贝

class Quote{
public:
    //该虚函数返回当前对象的一份动态分配的拷贝
    virtual Quote* clone() const & { return new Quote(*this);}
    virtual Quote* clone() && { return new Quote(std::move(*this)); }
};

class Bulk_quote : public Quote{
public:
    virtual Bulk_quote* clone() const & { return new Bulk_quot(*this);}
    virtual Bulk_quot* clone() && 
    { return new Bulk_quot(std::move(*this)); 
};

class Basket {
public:
    void add_item( const Quote &sale)
        { items.insert(std::shared_ptr<Quote>(sale.clone()); }
    void add_item( Quote &&sale)
        { items.insert(std::shared_ptr<Quote>(std::move(sale).clone()); }		
};

猜你喜欢

转载自blog.csdn.net/accumulating_mocai/article/details/83620647