Template Collection Classes Revisited: The CArray Class
In the Ex15b example in Chapter 15, you saw the MFC library CTypedPtrList template collection class, which was used to store a list of pointers to CStudent objects. Another collection class, CArray, is appropriate for our next example, Ex17b. This class is different from CTypedPtrList in two ways. First, it's an array, with elements accessible by index, just like CStringArray in Ex17a. Second, the array holds actual objects, not pointers to objects. In Ex17b, the elements are CRect objects. The elements' class does not have to be derived from CObject, and indeed, CRect is not.As in Ex17b, a typedef makes the template collection easier to use. We'll use the following statement to define an array class that holds CRect objects and whose functions take CRect reference parameters. (It's cheaper to pass a 32-bit pointer than to copy a 128bit object.)
typedef CArray<CRect, CRect&> CRectArray;
To use the template array, you declare an instance of CRectArray and then you call CArray member functions such as SetSize. You can also use the CArray subscript operator to get and set elements.The template classes CArray, CList, and CMap are easy to use if the element class is sufficiently simple. The CRect class fits that description because it contains no pointer data members. Each template class uses a global function, SerializeElements, to serialize all the elements in the collection. The default SerializeElements function does a bitwise copy of each element to and from the archive.If your element class contains pointers or is otherwise complex, you must write your own SerializeElements function. For example, if you write this function for the rectangle array (not required), your code will look like this:
void AFXAPI SerializeElements(CArchive& ar, CRect* pNewRects,
int nCount)
{
for (int i = 0; i < nCount; i++, pNewRects++) {
if (ar.IsStoring()) {
ar << *pNewRects;
}
else {
ar >> *pNewRects;
}
}
}
When the compiler sees this function, it uses the function to replace the SerializeElements function inside the template. This only works, however, if the compiler sees the SerializeElements prototype before it sees the template class declaration.
Note | The template classes depend on two other global functions, ConstructElements and DestructElements. Starting with Microsoft Visual C++ version 4.0, these functions call the element class constructor and destructor for each object. Therefore, there's no real need to replace them. |