標準庫自己其元件的容器類。也就是說,如果您有:
class Base {};
class Child : public Base {};
std::list <Base> myList;
std::list <Base> *pMyList;
隨後的myList
的元素只能爲(引用)Base
類型的對象進行訪問。您可以存儲Base
類型的元素(例如push_back
,emplace_back
),並獲取參考/副本(例如front
或通過迭代器),例如,請參見cppreference/list。讓我們來看看push_back
:
void push_back(const value_type&);
哪裏value_type
是你傳遞給std::list
第一個模板參數。在你的情況下,這是PartitionT < CompareJobReady, CompareJobRunning >
,或在上面的例子中,它是Base
。 push_back
實際上副本您傳遞的參數並使該副本成爲新元素。這是爲什麼?因爲新元素可以歸列表所有。列表可以在列表本身被銷燬時銷燬該元素,並且如果您移動/交換兩個列表,則將它傳遞給另一個列表。如果元素沒有被複制並從外部銷燬,則列表將包含一個被破壞的元素 - 這會破壞列表給出的保證(並且它不會很好)。
另一個示例(簡化,不是很準確):list
通過分配器爲其元素分配內存。這裏的默認分配器是std::allocator<Base>
。它僅爲存儲類型爲Base
的對象所需的元素分配儘可能多的內存。
當你做這樣的事情pMyList = new std::list <Child>;
,右側的結果是「指針std::list<Child>
」,而左側的類型是「指向std::list<Base>
」。這兩種類型無關,因爲std::list<Base>
不會繼承或定義轉換爲std::list<Child>
。有一些原因爲什麼這很好,一個是泛型編程需要知道它處理的是什麼類型。多態是一種抽象,所以你不必在編譯時知道你正在處理的是什麼類型。
C++中的多態性通過指針或引用工作。所以,如果你想安排在不可知這種類型的列表中的一些Child
對象(例如只知道Base
類型),您必須將它們存儲爲指針:
std::list < std::shared_ptr<Base> > myList2;
myList2.push_back(new Child); // better not use, there's a caveat (1)
// approach w/o this caveat
std::shared_ptr<Base> pNewChild(new Child); // or make_shared
myList2.push_back(pNewChild);
注意我這裏使用shared_ptr
,你可以使用一個unique_ptr
如果這適合你更好的目的,但你不應該使用原始ptrs:因爲這myList2
擁有它的shared_ptr
元素和shared_ptr
擁有共享所有權的對象(類型爲Base),myList2
間接擁有Child
將ptrs存儲在列表中的對象。由於原料ptrs不表示所有權,例如誰不負責銷燬它們。閱讀更多關於"Rule of Zero"。
(1)有一個警告,請參閱boost,雖然它不影響此示例。
如果你真的想選擇的地方比較程序類來完成泛型編程,你「必須堅持編譯時間」:您的列表類型(type *p
)不應該被固定爲list<Base>
,而是通用(使用模板)以及您在其上使用的所有算法都必須是通用的。你不能(簡單地*)混合泛型編程和類型的運行時選擇,因爲泛型編程就是在編譯時創建代碼。
*有一個黑客,它允許它,濫用RTTI,因此非常緩慢。
來源
2012-11-08 15:55:56
dyp
這是來自標準庫的'std :: list'嗎? – dyp
是的,如果我沒有提到它,對不起。 – user1809140