Template-Based Classes
The new home for Visual Studio documentation is Visual Studio 2017 Documentation on docs.microsoft.com.
The latest version of this topic can be found at Template-Based Classes.
This article explains the type-safe template-based collection classes in MFC version 3.0 and later. Using these templates to create type-safe collections is more convenient and helps provide type safety more effectively than using the collection classes not based on templates.
MFC predefines two categories of template-based collections:
Simple array, list, and map classes
CArray
,CList
,CMap
Arrays, lists, and maps of typed pointers
CTypedPtrArray
,CTypedPtrList
,CTypedPtrMap
The simple collection classes are all derived from class CObject
, so they inherit the serialization, dynamic creation, and other properties of CObject
. The typed pointer collection classes require you to specify the class you derive from — which must be one of the nontemplate pointer collections predefined by MFC, such as CPtrList
or CPtrArray
. Your new collection class inherits from the specified base class, and the new class's member functions use encapsulated calls to the base class members to enforce type safety.
For more information about C++ templates, see Templates in the C++ Language Reference.
Using Simple Array, List, and Map Templates
To use the simple collection templates, you need to know what kind of data you can store in these collections and what parameters to use in your collection declarations.
Simple Array and List Usage
The simple array and list classes, CArray and CList, take two parameters: TYPE and ARG_TYPE
. These classes can store any data type, which you specify in the TYPE parameter:
Fundamental C++ data types, such as
int
,char
, and floatC++ structures and classes
Other types that you define
For convenience and efficiency, you can use the ARG_TYPE
parameter to specify the type of function arguments. Typically, you specify ARG_TYPE
as a reference to the type you named in the TYPE parameter. For example:
CArray<int, int> myArray;
CList<CPerson, CPerson&> myList;
The first example declares an array collection, myArray
, that contains int
s. The second example declares a list collection, myList
, that stores CPerson
objects. Certain member functions of the collection classes take arguments whose type is specified by the ARG_TYPE
template parameter. For example, the Add member function of class CArray
takes an ARG_TYPE
argument:
CArray<CPerson, CPerson&> personArr;
CPerson person;
personArr.Add(person);
Simple Map Usage
The simple map class, CMap, takes four parameters: KEY, ARG_KEY
, VALUE, and ARG_VALUE
. Like the array and list classes, the map classes can store any data type. Unlike arrays and lists, which index and order the data they store, maps associate keys and values: You access a value stored in a map by specifying the value's associated key. The KEY parameter specifies the data type of the keys used to access data stored in the map. If the type of KEY is a structure or class, the ARG_KEY
parameter is typically a reference to the type specified in KEY. The VALUE parameter specifies the type of the items stored in the map. If the type of ARG_VALUE
is a structure or class, the ARG_VALUE
parameter is typically a reference to the type specified in VALUE. For example:
CMap< int, int, MY_STRUCT, MY_STRUCT& > myMap1;
CMap< CString, LPCTSTR, CPerson, CPerson& > myMap2;
The first example stores MY_STRUCT
values, accesses them by int
keys, and returns accessed MY_STRUCT
items by reference. The second example stores CPerson
values, accesses them by CString
keys, and returns references to accessed items. This example might represent a simple address book, in which you look up persons by last name.
Because the KEY parameter is of type CString
and the KEY_TYPE parameter is of type LPCSTR
, the keys are stored in the map as items of type CString
but are referenced in functions such as SetAt
through pointers of type LPCSTR
. For example:
CMap< CString, LPCTSTR, CPerson, CPerson& > myMap;
CPerson person;
LPCTSTR lpstrName = _T("Jones");
myMap.SetAt(lpstrName, person);
Using Typed-Pointer Collection Templates
To use the typed-pointer collection templates, you need to know what kinds of data you can store in these collections and what parameters to use in your collection declarations.
Typed-Pointer Array and List Usage
The typed-pointer array and list classes, CTypedPtrArray and CTypedPtrList, take two parameters: BASE_CLASS
and TYPE. These classes can store any data type, which you specify in the TYPE parameter. They are derived from one of the nontemplate collection classes that stores pointers; you specify this base class in BASE_CLASS
. For arrays, use either CObArray
or CPtrArray
. For lists, use either CObList
or CPtrList
.
In effect, when you declare a collection based on, say CObList
, the new class not only inherits the members of its base class, but it also declares a number of additional type-safe member functions and operators that help provide type safety by encapsulating calls to the base class members. These encapsulations manage all necessary type conversion. For example:
CTypedPtrArray<CObArray, CPerson*> myArray;
CTypedPtrList<CPtrList, MY_STRUCT*> myList;
The first example declares a typed-pointer array, myArray
, derived from CObArray
. The array stores and returns pointers to CPerson
objects (where CPerson
is a class derived from CObject
). You can call any CObArray
member function, or you can call the new type-safe GetAt
and ElementAt
functions or use the type-safe [ ] operator.
The second example declares a typed-pointer list, myList
, derived from CPtrList
. The list stores and returns pointers to MY_STRUCT
objects. A class based on CPtrList
is used for storing pointers to objects not derived from CObject
. CTypedPtrList
has a number of type-safe member functions: GetHead
, GetTail
, RemoveHead
, RemoveTail
, GetNext
, GetPrev
, and GetAt
.
Typed-Pointer Map Usage
The typed-pointer map class, CTypedPtrMap, takes three parameters: BASE_CLASS
, KEY, and VALUE. The BASE_CLASS
parameter specifies the class from which to derive the new class: CMapPtrToWord
, CMapPtrToPtr
, CMapStringToPtr
, CMapWordToPtr
, CMapStringToOb
, and so on. KEY is analogous to KEY in CMap
: It specifies the type of the key used for lookups. VALUE is analogous to VALUE in CMap
: It specifies the type of object stored in the map. For example:
CTypedPtrMap<CMapPtrToPtr, CString, MY_STRUCT*> myPtrMap;
CTypedPtrMap<CMapStringToOb, CString, CPerson*> myPersonMap;
The first example is a map based on CMapPtrToPtr — it uses CString
keys mapped to pointers to MY_STRUCT
. You can look up a stored pointer by calling a type-safe Lookup
member function. You can use the [ ] operator to look up a stored pointer and add it if not found. And you can iterate the map using the type-safe GetNextAssoc
function. You can also call other member functions of class CMapPtrToPtr
.
The second example is a map based on CMapStringToOb — it uses string keys mapped to stored pointers to CMyObject
objects. You can use the same type-safe members described in the previous paragraph, or you can call members of class CMapStringToOb
.
Note
If you specify a class or struct
type for the VALUE parameter, rather than a pointer or reference to the type, the class or structure must have a copy constructor.
For more information, see How to Make a Type-Safe Collection.