引題:在C++中,對於運行時類型識別問題。在程序中使用引用或者指針在運行時動態識別對象類型。然而使用指針或者引用卻增長了用戶負擔(在繼承體系中,沒有明確的基類到派生類的轉換,必須用戶顯示轉換並將結果對象加入容器中。可是這樣的作法結果倒是派生對象部分紅員是未初始化的)。函數
對於這一問題,能夠將對象指針 保存在容器中來解決。但此時,用戶必須明確容器中指針和 對象的同步性(不能只有指針而對象不存在或者收指針不存在,對象存在)。this
更好的解決方案就是句柄類了:spa
C++ 中一個通用的技術是定義包裝(cover)類或句柄類。句柄類存儲和管 理基類指針。指針所指對象的類型能夠變化,它既能夠指向基類類型對象又能夠 指向派生類型對象。用戶經過句柄類訪問繼承層次的操做。由於句柄類使用指針 執行操做,虛成員的行爲將在運行時根據句柄實際綁定的對象的類型而變化。因 此,句柄的用戶能夠得到動態行爲但無須操心指針的管理。設計
包裝了繼承層次的句柄有兩個重要的設計考慮因素:指針
句柄包裝指針,用戶能夠將該句柄類看成指針使用,卻不用去管理指針指向的對象。(句柄類更像是一箇中介控制者)code
定義方案:對象
1. 使用類包裝指針,包裝計數器(每一個對象都有各自的這兩個成員)blog
2.使用類包裝指針,包裝計數器指針(資源和計數器共享)繼承
句柄類除了定義構造,拷貝構造,賦值,還須要定義引用,解引用(使之看起來更像是指針)接口
對於構造函數:
1個默認構造函數初始化成員爲0;
1個構造函數聲明指定對象類型的句柄。
那麼問題來了,若是用戶並不知曉用 繼承體系中具體哪一個層次對象進行初始化,如何作呢。
解決這個問題的通用方法是定義虛操做進行復制,咱們稱將 該操做命名爲 clone。(克隆):
對於繼承層次中的每一個類,增長一個虛克隆函數eg:
class Item_base { public: virtual Item_base* clone() const { return new Item_base(*this); } };
有了克隆函數那麼 句柄類的定義以下:
Sales_item::Sales_item(const Item_base &item): p(item.clone()), use(new std::size_t(1)) { }
對於繼承層次中 若是須要邏輯比較函數,一個好的作法是 定義內部比較,比較內部核心成員。
inline bool compare(const Sales_item &lhs, const Sales_item &rhs) { return lhs->book() < rhs->book(); }
使用帶關聯容器的比較器
要有效地工做,關聯容器須要對每一個操做使用同一比較函數。然而,指望用 戶每次記住比較函數是不合理的,尤爲是,沒有辦法檢查每一個調用使用同一比較 函數。所以,容器記住比較函數是有意義的。經過將比較器存儲在容器對象中, 能夠保證比較元素的每一個操做將一致地進行。
這種作法,實質上就是使用函數指針,函數回調實現真正的比較。
// type of the comparison function used to order the multiset
typedef bool (*Comp)(const Sales_item&, const Sales_item&);
關聯容器的每一個構造函數使咱們可以提供比較函數的名 字。能夠這樣定義使用 compare 函數的空 multiset:
std::multiset<Sales_item, Comp> items(compare);
multiset 是STL中的聯合容器。。在頭文件<set>中,具體用法請參看《STL源碼剖析》
參考(C++primer)