本文說明如何為您自己的數據類型建立型別安全集合。 主題包括:
Microsoft基礎類別庫會根據C++範本提供預先定義的型別安全集合。 因為這些類別是範本,所以這些類別有助於提供型別安全性和易於使用,而不需要針對此目的使用非範本類別所涉及的類型轉型和其他額外工作。 MFC 範例 COLLECT 示範如何在 MFC 應用程式中使用範本型集合類別。 一般而言,您可以隨時撰寫新的集合程序代碼,使用這些類別。
使用 Template-Based 類別進行型別安全性
使用範本型類別
宣告集合類別類型的變數。 例如:
CList<int, int> m_intList;
呼叫集合對象的成員函式。 例如:
m_intList.AddTail(100); m_intList.RemoveAll();
如有必要,請實作 協助程式函 式和 SerializeElements。 如需實作這些函式的資訊,請參閱 實作協助程式函式。
此範例顯示整數清單的宣告。 步驟 1 中的第一個參數是儲存為清單元素的數據類型。 第二個參數會指定如何將數據傳遞至集合類別的成員函式,以及 從 傳回數據,例如 Add
和 GetAt
。
實作輔助函式
範本型集合類別 CArray
、 CList
和 CMap
使用五個全域協助程式函式,您可以視需要自定義衍生集合類別。 如需這些協助程式函式的資訊,請參閱 MFC 參考中的集合類別協助程式。 串行化函式的實作對於大部分範本型集合類別而言是必要的。
元素序列化
CArray
、 CList
和 CMap
類別會呼叫 SerializeElements
來儲存集合專案,或從封存中讀取它們。
協助函式的預設實作 SerializeElements
會根據物件是要儲存在封存中還是從封存中擷取,進行位元寫入或位元讀取操作。 如果此動作不適合,請覆蓋 SerializeElements
。
如果您的集合儲存衍生自CObject
的物件,且您在集合專案類別的實作中使用IMPLEMENT_SERIAL
巨集,則可以利用CArchive
和CObject
內建的序列化功能。
CArray< CPerson, CPerson& > personArray;
template <> void AFXAPI SerializeElements <CPerson>(CArchive& ar,
CPerson* pNewPersons, INT_PTR nCount)
{
for (int i = 0; i < nCount; i++, pNewPersons++)
{
// Serialize each CPerson object
pNewPersons->Serialize(ar);
}
}
CArchive
的多載插入運算元會為每個 CObject::Serialize
物件呼叫 CPerson
(或該函式的覆寫)。
使用非模板集合類別
MFC 也支援 MFC 1.0 版引進的集合類別。 這些類別不是以範本為基礎。 它們可用來包含支援型 CObject*
別、 UINT
、 DWORD
和 CString
的數據。 您可以使用這些預先定義的集合(例如 CObList
)來保存衍生自 CObject
的任何物件集合。 MFC 也提供其他預先定義的集合來保存基本類型,例如 UINT
和 void 指標 (void*
)。 不過,一般而言,定義您自己的型別安全集合,以保存更特定類別及其衍生項目的物件通常很有用。 請注意,使用不是以範本為基礎的集合類別,比使用基於範本的類別需要更多的工作。
有兩種方式可以建立具有非範本集合的類型安全集合:
請使用非範本集合,必要時進行型別轉換。 這是更簡單的方法。
衍生自並擴充非範本型別安全集合。
若要搭配類型轉換使用非範本集合
直接使用其中一個非樣本類別,例如
CWordArray
。例如,您可以建立
CWordArray
並將任何 32 位值加入其中,然後擷取它們。 沒有什麼可做的事。 您只要使用預先定義的功能。您也可以使用預先定義的集合,例如
CObList
,來保存衍生自CObject
的任何物件。CObList
集合被定義為用於保存CObject
指標。 當您從清單中擷取物件時,可能必須將結果轉換成適當的類型,因為函式會將CObList
指標傳回至CObject
。 例如,如果您將CPerson
物件儲存在CObList
集合中,則必須將擷取的元素轉換為指向CPerson
物件的指標。 下列範例會使用CObList
集合來儲存CPerson
物件:CPerson* p1 = new CPerson(); CObList myList; myList.AddHead(p1); // No cast needed CPerson* p2 = (CPerson*)myList.GetHead();
使用預先定義的集合類型並視需要轉換的這項技術,可能足以滿足您的許多集合需求。 如果您需要進一步的功能或更多類型安全性,請使用以範本為基礎的類別,或遵循下一個程式。
衍生和擴充非範本型別安全集合
從其中一個預先定義的非範本類別衍生您自己的集合類別。
當您衍生類別時,可以新增型別安全包裝函式,為現有函式提供型別安全介面。
例如,如果您從
CObList
衍生清單來保存CPerson
物件,您可以新增包裝函AddHeadPerson
式和GetHeadPerson
,如下所示。class CPersonList : public CObList { public: void AddHeadPerson(CPerson* person) { AddHead(person); } const CPerson* GetHeadPerson() { return (CPerson*)GetHead(); } };
這些包裝函式提供型別安全的方式,可從衍生清單新增和擷取
CPerson
物件。 您可以看到,在GetHeadPerson
函式中,您只是在封裝類型轉換。您也可以通過定義新函式來擴充集合的功能,而不是僅僅將現有功能包裝在類型安全包裝函式中。 例如, 刪除 CObject 集合中的所有物件 一文描述一個函式,可刪除清單中包含的所有物件。 此函式可以新增至衍生類別做為成員函式。