基于模板的类
本文介绍 MFC 版本 3.0 及更高版本中基于类型安全模板的集合类。 使用这些模板创建类型安全集合比使用不基于模板的集合类更方便,并且有助于更有效地提供类型安全性。
MFC 预定义了两类基于模板的集合:
-
CArray
,CList
,CMap
-
CTypedPtrArray
,CTypedPtrList
,CTypedPtrMap
简单集合类均派生自 CObject
,因此它们继承了 CObject
的序列化、动态创建和其他属性。 类型化指针集合类要求你指定派生自的类,该类必须是 MFC 预定义的非模板指针集合之一,例如 CPtrList
或 CPtrArray
。 新集合类继承自指定的基类,并且新类的成员函数使用对基类成员的封装调用来强制实施类型安全性。
有关 C++ 模板的详细信息,请参阅 C++ 语言参考中的模板。
使用简单数组、列表和映射模板
若要使用简单集合模板,需要知道可以在这些集合中存储哪些类型的数据以及在集合声明中使用哪些参数。
简单数组和列表用法
简单数组和列表类(CArray 和 CList)采用两个参数:TYPE 和 ARG_TYPE
。 这些类可以存储在 TYPE 参数中指定的任何数据类型:
基本 C++ 数据类型,例如
int
、char
和float
C++ 结构和类
定义的其他类型
为了方便和高效性,可以使用 ARG_TYPE 参数指定函数参数的类型。 通常,将 ARG_TYPE 指定为对在 TYPE 参数中命名的类型的引用。 例如:
CArray<int, int> myArray;
CList<CPerson, CPerson &> myList;
第一个示例声明了一个数组集合 myArray
,其中包含 **int
**s。 第二个示例声明了一个列表集合 myList
,用于存储 CPerson
对象。 集合类的某些成员函数采用类型由 ARG_TYPE 模板参数指定的参数。 例如,类 CArray
的 Add
成员函数采用 ARG_TYPE 参数:
CArray<CPerson, CPerson &> personArr;
CPerson person;
personArr.Add(person);
简单映射用法
简单映射类 CMap 采用四个参数:KEY、ARG_KEY、VALUE 和 ARG_VALUE。 与数组和列表类一样,映射类可以存储任何数据类型。 与数组和列表不同,数组和列表对它们存储的数据进行索引和排序,映射关联键和值:通过指定值的关联键来访问存储在映射中的值。 KEY 参数指定用于访问映射中存储数据的键的数据类型。 如果 KEY 的类型是结构或类,则 ARG_KEY 参数通常是对 KEY 中指定的类型的引用。 VALUE 参数指定存储在映射中的项的类型。 如果 ARG_VALUE 的类型是结构或类,则 ARG_VALUE 参数通常是对 VALUE 中指定的类型的引用。 例如:
CMap<int, int, MY_STRUCT, MY_STRUCT &> myMap1;
CMap<CString, LPCTSTR, CPerson, CPerson &> myMap2;
第一个示例存储 MY_STRUCT
值,通过 int
键访问它们,并通过引用返回访问的 MY_STRUCT
项。 第二个示例存储 CPerson
值,通过 CString
键访问它们,并返回对访问项的引用。 此示例可能表示一个简单的通讯簿,在该通讯簿中按姓氏查找人员。
由于 KEY 参数属于 CString
类型,而 KEY_TYPE 参数属于 LPCSTR
类型,因此键作为 CString
类型的项存储在映射中,但在 SetAt
等函数中通过 LPCSTR
类型的指针引用。 例如:
CMap<CString, LPCTSTR, CPerson, CPerson &> myMap;
CPerson person;
LPCTSTR lpstrName = _T("Jones");
myMap.SetAt(lpstrName, person);
使用类型化指针集合模板
若要使用类型化指针集合模板,需要知道可以在这些集合中存储哪些类型的数据以及在集合声明中使用哪些参数。
类型化指针数组和列表用法
类型化指针数组和列表类 CTypedPtrArray 和 CTypedPtrList 采用两个参数:BASE_CLASS 和 TYPE。 这些类可以存储在 TYPE 参数中指定的任何数据类型。 它们派生自存储指针的非模板集合类之一;在 BASE_CLASS 中指定此基类。 对于数组,请使用 CObArray
或 CPtrArray
。 对于列表,请使用 CObList
或 CPtrList
。
实际上,声明一个基于 CObList
的集合时,新类不仅继承了其基类的成员,而且还声明了许多额外的类型安全成员函数和运算符,它们通过封装对基类成员的调用来帮助提供类型安全性。 这些封装管理所有必要的类型转换。 例如:
CTypedPtrArray<CObArray, CPerson *> myArray;
CTypedPtrList<CPtrList, MY_STRUCT *> myList;
第一个示例声明派生自 CObArray
的类型化指针数组 myArray
。 该数组存储并返回指向 CPerson
对象的指针(其中 CPerson
是派生自 CObject
的类)。 可以调用任何 CObArray
成员函数,也可以调用新的类型安全 GetAt
和 ElementAt
函数或使用类型安全 [ ] 运算符。
第二个示例声明派生自 CPtrList
的类型化指针列表 myList
。 该列表存储并返回指向 MY_STRUCT
对象的指针。 基于 CPtrList
的类用于存储指向不是派生自 CObject
的对象的指针。 CTypedPtrList
有许多类型安全的成员函数:GetHead
、GetTail
、RemoveHead
、RemoveTail
、GetNext
、GetPrev
和 GetAt
。
类型化指针映射用法
类型化指针映射类 CTypedPtrMap 采用三个参数:BASE_CLASS、KEY 和 VALUE。 BASE_CLASS 参数指定派生新类的类:CMapPtrToWord
、CMapPtrToPtr
、CMapStringToPtr
、CMapWordToPtr
、CMapStringToOb
等。 KEY 类似于 CMap
中的 KEY:它指定用于查找的键的类型。 VALUE 类似于 CMap
中的 VALUE:它指定存储在映射中的对象的类型。 例如:
CTypedPtrMap<CMapPtrToPtr, CString, MY_STRUCT*> myPtrMap;
CTypedPtrMap<CMapStringToOb, CString, CPerson*> myPersonMap;
第一个示例是基于 CMapPtrToPtr
的映射,它使用映射到指向 MY_STRUCT
的指针的 CString
键。 可以通过调用类型安全的 Lookup
成员函数来查找存储的指针。 可以使用 [ ] 运算符查找存储的指针,如果未找到则添加它。 可以使用类型安全的 GetNextAssoc
函数循环访问映射。 还可以调用类 CMapPtrToPtr
的其他成员函数。
第二个示例是基于 CMapStringToOb
的映射,它使用映射到存储的指向 CMyObject
对象的指针的字符串键。 可以使用上一段中所述的相同类型安全成员,也可以调用类 CMapStringToOb
的成员。
注意
如果为 VALUE 参数指定 class
或 struct
类型,而不是指向该类型的指针或引用,则类或结构必须具有复制构造函数。
有关详细信息,请参阅如何创建类型安全集合。