1. 程式人生 > >C++Primer_Chap15_面向物件程式設計_List08_容器和繼承_筆記

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()); }		
};