C++Primer_Chap15_面向物件程式設計_List08_容器和繼承_筆記
阿新 • • 發佈:2018-11-08
當我們使用容器存放繼承體系中的物件時,通常必須採用間接儲存的方式。因為不允許在容器中儲存不同型別的元素,所以不能把具有繼承關係的多種型別的物件之間存放在容器中。
在容器中放置(智慧)指標而非物件
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()); }
};