本文介绍 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和floatC++结构和类
定义的其他类型
为方便和提高效率,可以使用 ARG_TYPE 参数来指定函数参数的类型。 通常,将 ARG_TYPE 指定为对 TYPE 参数中命名的类型的引用。 例如:
CArray<int, int> myArray;
CList<CPerson, CPerson &> myList;
第一个示例声明包含 ****myArrays 的数组集合int。 第二个示例声明一个用于存储myList对象的列表集合CPerson。 集合类的某些成员函数接受类型由 ARG_TYPE 模板参数指定的参数。 例如, Add 类 CArray 的成员函数采用 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);
使用类型化指针集合模板
若要使用类型指针集合模板,需要知道可在这些集合中存储的数据类型以及要用于集合声明中的参数。
Typed-Pointer 数组和列表使用情况
类型指针数组和列表类 CTypedPtrArray 和 CTypedPtrList 采用两个参数: BASE_CLASS 和 TYPE。 这些类可以存储你在 TYPE 参数中指定的任何数据类型。 它们派生自存储指针的非模板集合类之一;在 BASE_CLASS中指定此基类。 对于数组,请使用 CObArray 或 CPtrArray。 对于列表,请使用 CObList 或 CPtrList 中的任意一个。
实际上,当您声明一个基于CObList的集合时,新类不仅继承其基类的成员,还声明了一些额外的类型安全成员函数和运算符,这些函数和运算符通过封装对基类成员的调用来提供类型安全。 这些封装管理所有必要的类型转换。 例如:
CTypedPtrArray<CObArray, CPerson *> myArray;
CTypedPtrList<CPtrList, MY_STRUCT *> myList;
第一个示例声明派生自myArray的类型指针数组CObArray。 数组存储并返回指向 CPerson 对象的指针(其中 CPerson 是派生自 CObject的类)。 可以调用任何 CObArray 成员函数,也可以调用新的类型安全 GetAt 函数和 ElementAt 函数,或使用 type-safe [ ] 运算符。
第二个示例声明了一个类型指针列表myList,该列表派生自CPtrList。 列表存储并返回指向 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 类似于 KEY in CMap:它指定用于查找的键的类型。 VALUE 类似于 VALUE in CMap:它指定存储在地图中的对象的类型。 例如:
CTypedPtrMap<CMapPtrToPtr, CString, MY_STRUCT*> myPtrMap;
CTypedPtrMap<CMapStringToOb, CString, CPerson*> myPersonMap;
第一个示例是基于 CMapPtrToPtr 的映射,它使用映射到指向 CString 的指针的 MY_STRUCT 键。 可以通过调用类型安全 Lookup 成员函数来查找存储的指针。 可以使用 [ ] 运算符查找存储的指针,并在找不到时添加它。 可以使用类型安全的 GetNextAssoc 函数循环访问映射。 还可以调用类 CMapPtrToPtr的其他成员函数。
第二个示例是基于 CMapStringToOb 的映射,它使用映射到存储的指向 CMyObject 对象的指针的字符串键。 可以使用上一段所述的相同类型安全成员,也可以调用类 CMapStringToOb的成员。
注释
如果为 class 参数指定struct或类型,而不是指定为该类型的指针或引用,则类或结构必须具有拷贝构造函数。
有关详细信息,请参阅 如何创建 Type-Safe 集合。