Upload
sangeethaag19
View
222
Download
0
Embed Size (px)
Citation preview
7/27/2019 7 Serialization and Collection Classesssdfsdf
1/18
Chapter 7
Serialization and CollectiOnClasses
Objectives
Explains the serialization mechanism provided in the Microsoft Foundation Class
Library (MFC).
Explain concept and need of Serialization in Document / View architecture.
List the MFC Classes used in serialization and how they work internally to
perform Serialization. CFile, CObject and CArchive classes.
Make a class serializable.
List collection classes. Iterate / Delete object from collection classes.
IntroductionThe basic idea of serialization is that an object should be able to write its current state, usually
indicated by the value of its member variables, to persistent storage. Later, the object can be re-
created by reading, or deserializing, the objects state from the storage. Serialization handles all
the details of object pointers and circular references to objects that are used when you serialize
an object. A key point is that the object itself is responsible for reading and writing its own state.
Serialization is an important concept in MFC programming because it is the basis for the
frameworks ability to open and save document in document / view architecture. This chaptercovers all the details of serialization and how to make a class serializable.
Need for Serialization1) For implementing the file reading and writing, without worrying about the format of the file you
are writing to.
2) Concatenating the objects onto the file and then reading them in the order they were written.
Classes involved in Serialization
CObject
CFile
CArchive
CObject
The basic serialization protocol and functionality are defined in the CObject class. By deriving
your class from CObject (or from a class derived from CObject), you gain access to the
serialization protocol and functionality ofCObject.
The Serialize member function, which is defined in the CObject class, is responsible for
actually serializing the data necessary to capture an objects current state. The Serialize
7/27/2019 7 Serialization and Collection Classesssdfsdf
2/18
Page 96 Serialization and Collection Classes
function has a CArchive argument (which will be covered soon ) that it uses to read and write
the object data. The CArchive object has a member function, IsStoring, which indicates
whether Serialize is storing (writing data) or loading (reading data). Using the results of
IsStoring as a guide, you either insert your objects data in the CArchive object with the
insertion operator ().
One of the most important feature of CObject is run-time class information that lets the
developer determine the information about an object such as class name and parent at run-
time.
The code to support RTCI resides in the macros like
DECLARE_DYNAMIC / IMPLEMENT_DYNAMIC
DECLARE_DYNCREATE / IMPLEMENT_ DYNCREATE
DECLARE_SERIAL / IMPLEMENT_SERIAL
The class derived from CObject can call IsKindOf( ) function which takes an argument that is
created by another macro , RUNTIME_CLASS. The CRuntimeClass contains a data member
m_wSchema. Serialization uses the WORD to give a class version. If , serialization is not
supported then m_wSchema is oxffff. You can specify your own Schema through the
IMPLEMENT_SERIAL macro as the third argument.The CObjects IsSerializable() function makes sure if the user has specified the correctmacros for Serialization by checking that the m_wSchema for the CRuntimeClass is not
0xffff.
CObject :: IsSerializable( )
BOOL CObject :: IsSerializable( ) const
{
return ( GetRuntimeClass( ) -> m_wSchema ! =
0xffff) ;
}
Does the MFC architecture with CObject as a root cause performance problems ?
C++ has to index the class virtual table at runtime to determine the correct function to
execute. CObject has five virtual functions , two of which are in the debug builds only , so they
dont really affect the release- build performance. The largest overhead with using virtual
function is the increased instance size from a virtual table.
Thus, the trade-off in deriving from CObject is 3 extra virtual functions added to your classes
virtual table in exchange for RTCI, dynamic creation, serialization and memory diagnostics.
CFile
CFile is the base class for Microsoft Foundation file classes. It directly provides unbuffered,
binary disk input/output services, and it indirectly supports text files and memory files through
its derived classes. CFile works in conjunction with the CArchive class to support
serialization
CFile family consists of the following :
CStdioFile , CMemFile ,CFile derivative class called CSharedFile and CFile itself.
CStdioFile : It is buffered , reading and writing non-binary ASCII files.CMemFile : It provides a base class for implementing shared memory through CFile
SEED Infotech Ltd.
http://hhobj_4.click%28%29/http://hhobj_4.click%28%29/7/27/2019 7 Serialization and Collection Classesssdfsdf
3/18
Serialization and Collection Classes Page 97
interface.
CSharedFile : Provides some memory sharing.
The hierarchical relationship between this class and its derived classes allows your program
to operate on all file objects through the polymorphic CFile interface. A memory file, for
example, behaves like a disk file.
Normally, a disk file is opened automatically on CFile construction and closed on destruction.
When you create a CFile Object , you specify a filename and file open mode.
E.g.
CFile myfile(filename, CFile :: modeCreate|CFile :: modeWrite);
CArchive
CArchive does not have a base class. MFC uses an object of the CArchive class as an
intermediary between the object to be serialized and the storage medium. This object is
always associated with a CFile object, from which it obtains the necessary information for
serialization, including the file name and whether the requested operation is a read or write.The object that performs a serialization operation can use the CArchive object without regard
to the nature of the storage medium.
CArchive object uses overloaded insertion () operators to perform
writing and reading operations.
There are two ways to create a CArchive object:
1) Implicit creation of a CArchive object via the framework
2) Explicit creation of a CArchive object
1. Implicit creation of a CArchive object via the framework
The most common, and easiest, way is to let the framework create a CArchive object foryour document on behalf of the Save, Save As, and Open commands on the File menu.
Your documents Serialize function then writes data to the CArchive object. Upon returnfrom yourSerialize function, the framework destroys the CArchive object and then theCFile object. Thus, if you let the framework create the CArchive object for your
document, all you have to do is implement the documents Serialize function that writesand reads to and from the archive. You also have to implement Serialize for anyCObject-derived objects that the documents Serialize function in turn serializes directlyor indirectly.
2. Explicit creation of a CArchive object
Besides serializing a document via the framework, there are other occasions when you
may need a CArchive object. For example, you might want to serialize data to and from
the Clipboard, represented by a CSharedFile object. Or, you may want to use a user
interface for saving a file that is different from the one offered by the framework. In this
case, you can explicitly create a CArchive object. You do this the same way the
framework does, using the following procedure.
1) Construct a CFile object or an object derived from CFile.
2) Pass the CFile object to the constructor for CArchive
E.g.
CFile theFile;
theFile.Open(..., CFile::modeWrite);CArchive archive(&theFile, CArchive::store);
SEED Infotech Ltd.
7/27/2019 7 Serialization and Collection Classesssdfsdf
4/18
Page 98 Serialization and Collection Classes
SEED Infotech Ltd.
7/27/2019 7 Serialization and Collection Classesssdfsdf
5/18
Serialization and Collection Classes Page 99
Serialization MacrosThe DECLARE_SERIAL macro is required in the declaration of classes that will support
serialization, as shown here:
class CPerson : public CObject
{
DECLARE_SERIAL( CPerson )
// rest of declaration follows...
};
The IMPLEMENT_SERIAL macro is used to define the various functions needed when you
derive a serializable class from CObject. You use this macro in the implementation file (.CPP) for
your class. The first two arguments to the macro are the name of the class and the name of its
immediate base class.
The third argument to this macro is a schema number. The schema number is essentially a
version number for objects of the class. Use an integer greater than or equal to 0 for the schemanumber.
The MFC serialization code checks the schema number when reading objects into memory. If the
schema number of the object on disk does not match the schema number of the class in memory,
the library will throw a CArchiveException, preventing your program from reading an incorrect
version of the object.
If you want your Serialize member function to be able to read multiple versions that is, files
written with different versions of the application you can use the value
VERSIONABLE_SCHEMA as an argument to the IMPLEMENT_SERIAL macro.
The following example shows how to use IMPLEMENT_SERIAL for a class, CPerson, that is
derived from CObject:
IMPLEMENT_SERIAL( CPerson, CObject, 1 )
How does IsStoring() and IsLoading() workThe following diagram shows the steps taken by MFC and CDocument / CObject derivatives
during serialization store process.
SEED Infotech Ltd.
7/27/2019 7 Serialization and Collection Classesssdfsdf
6/18
Page 100 Serialization and Collection Classes
In first step CDocument :: OnSaveDocument( ) creates a CArchive object in store mode and
attaches to a file already opened by the Common Dialog.
Next OnSaveDocument( ) calls the documents Serialize( ) method and finally closes the
archive.
In steps 3 - 5 the CMyDocument :: OnSaveDocument( ) is called which checks if the archive
is storing via IsStoring( ) and uses the insertion operator for writing , as shown in the fifth step.
In steps 6- 8 the insertion operator calls the CArchive::WriteObject ( ) which calls the
WriteClass(), then Serialize( ) for the CMyDocument object. From steps 9-13 the actual data is written into the output buffer. Finally the Archive is closed
by CDocument :: OnSaveDocument( ) as shown above.
SEED Infotech Ltd.
CDocument :: OnSaveDocument()
[ doccore.cpp]
CMyDocument :: Serialize()
CArchive :: IsStoring()
operator
7/27/2019 7 Serialization and Collection Classesssdfsdf
7/18
Serialization and Collection Classes Page 101
Steps taken while reading the same object that isstored
The framework unwinds what is wrote in the save operation when reading. The framework
can make sure that the data is read in the order that is written.
Making a class SerializableThere are five main steps to make a class Serializable :
Steps :
1) Deriving your class from CObject (or from some class derived from CObject).
2) Using the DECLARE_SERIAL macro in the class declaration.
3) Overriding the Serialize member function.
4) Defining a constructor that takes no arguments.
5) Using the IMPLEMENT_SERIAL macro in the implementation file for your class.
6) If you call Serialize directly rather than through the >> and > ( CArchive& , CMyClass* )
CArchive :: ReadObject ( )
CArchive :: Serialize ( )
CMyClass:: IsStoring ( )
CArchive :: operator >> ( WORD)
CArchive :: operator >> (DWORD)
CArchive :: Close( )
CDocument :: OnOpenDocument( )
[ doccore.cpp]
operator >> ( CArchive& , point )
CArchive :: Read( )
7/27/2019 7 Serialization and Collection Classesssdfsdf
8/18
Page 102 Serialization and Collection Classes
Overriding a Serialize functionCall your base class version of Serialize to make sure that the inherited portion of the object is
serialized.
Insert or extract the member variables specific to your class. The insertion and extraction
operators interact with the archive class to read and write the data.
The following eg shows how to implement Serialize for the CPerson class declared above
class CPerson : public CObject
{
DECLARE_SERIAL (CPerson);
CString m_fname;
WORD m_lname;
public:
virtual void Serialize ( CArchive& ar)
};
void CPerson ::Serialize ( CArchive& ar)
{
CObject::Serialize ( ar ); //call base class
//function first
if ( ar.IsStoring ( ) ){
ar m_fname;
ar >> m_lname;
}
Collection ClassesMFC contains a number of ready-to-use lists, arrays, and maps that are referred to as collection
classes. A collection is a very useful programming idiom for holding and processing groups of
class objects or groups of standard types. A collection object appears as a single object. Class
member functions can operate on all elements of the collection.
MFC supplies two kinds of collection classes:
Collection classes based on templates
Collection classes not based on templatesThe collection template classes are based on C++ templates, but the original collection classes
released with MFC version 1.0 not based on templates are still available.
Most collections can be archived or sent to a dump context. The Dump and Serialize member
functions for CObject pointer collections call the corresponding functions for each of their
elements. Some collections cannot be archived for example, pointer collections.
When you program with the application framework, the collection classes will be especially useful
for implementing data structures in your document class.
The Microsoft Foundation Class Library provides collection classes to manage groups of objects.
These classes are of two types:
Collection classes created from C++ templates
Collection classes not created from templates
SEED Infotech Ltd.
7/27/2019 7 Serialization and Collection Classesssdfsdf
9/18
Serialization and Collection Classes Page 103
MFC predefines two categories of template-based collections:
Simple array, list, and map classes - CArray, CList, CMap
Arrays, lists, and maps - CTypedPtrArray,CTypedPtrList,
of typed pointers 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 orCPtrArray.
Your new collection class inherits from the specified base class, and the new classs member
functions use encapsulated calls to the base class members to enforce type safety.
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 arrays and lists 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:
1) Fundamental C++ data types, such as int, char, and float
2) C++ structures and classes
3) Other types that you define
For convenience and efficiency, you can use the ARG_TYPEparameter to specify the type of
function arguments. Typically, you specifyARG_TYPEas a reference to the type you namedin the TYPEparameter. For example:
CArray myArray;
CList myList;
The first example declares an array collection, myArray, which contains ints. The second
example declares a list collection, myList, which stores CPerson objects.
Certain member functions of the collection classes take arguments whose type is specified by
theARG_TYPEtemplate parameter. For example, the Add member function of class CArray
takes anARG_TYPEargument:
CArray myArray;CPerson person;
myArray->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 values associated key.
The KEYparameter 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 areference to the type specified in KEY. The VALUEparameter specifies the type of the items
stored in the map.
SEED Infotech Ltd.
7/27/2019 7 Serialization and Collection Classesssdfsdf
10/18
Page 104 Serialization and Collection Classes
If the type ofARG_VALUEis a structure or class, the ARG_VALUEparameter is typically a
reference to the type specified in VALUE.
For example:
CMap< int, int, MY_STRUCT, MY_STRUCT& > myMap1;
CMap< CString, LPCSTR, 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, LPCSTR, CPerson, CPerson& > myMap2;
CPerson person;
LPCSTR lpstrName = "Jones";myMap2->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 youspecify in the TYPE parameter. They are derived from one of the nontemplate collection
classes that store pointers; you specify this base class in BASE_CLASS. For arrays, use
eitherCObArray orCPtrArray. For lists, use eitherCObList orCPtrList.
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 provide type safety by encapsulating calls to the base
class members. These encapsulations manage all necessary type conversion.
For example:
CTypedPtrArray myArray;
CTypedPtrList 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
SEED Infotech Ltd.
7/27/2019 7 Serialization and Collection Classesssdfsdf
11/18
Serialization and Collection Classes Page 105
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. KEYis analogous to KEYin CMap: it specifies the type of the
key used for lookups. VALUEis analogous to VALUE in CMap: it specifies the type of object
stored in the map.
For example:
CTypedPtrMap myPtrMap;
CTypedPtrMap
myObjectMap;
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 tostored 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.
NoteIf you specify a class orstruct type for the VALUEparameter, rather than a pointer or
reference to the type, the class or structure must have a copy constructor.
The Microsoft Foundation Class Library provides predefined type-safe collections based
on C++ templates. Because they are templates, these classes provide type safety and
ease of use without the type-casting and other extra work involved in using a nontemplate
class for this purpose.
Serializing Elements
The CArray, CList, and CMap classes call SerializeElements to store collection elements to or
read them from an archive.
The default implementation of the SerializeElements helper function does a bitwise write from
the objects to the archive, or a bitwise read from the archive to the objects, depending on
whether the objects are being stored in or retrieved from the archive. Override
SerializeElements if this action is not appropriate.
If your collection stores objects derived from CObject and you use the IMPLEMENT_SERIAL
macro in the implementation of the collection element class, you can take advantage of theserialization functionality built into CArchive and CObject
CPerson : public CObject { . . . };
CArray< CPerson, CPerson& > personArray;
void SerializeElements( CArchive& ar, CPerson* pNewPersons, int nCount )
{
for ( int i = 0; i < nCount; i++, pNewPersons++ )
{ // Serialize each CPerson object
pNewPersons->Serialize( ar );
}
}
The overloaded insertion operators for CArchive call CObject::Serialize (or an override of
SEED Infotech Ltd.
7/27/2019 7 Serialization and Collection Classesssdfsdf
12/18
Page 106 Serialization and Collection Classes
that function) for each CPerson object.
Using Nontemplate Collection Classes
MFC also supports the collection classes introduced with MFC version 1.0. These classes are
not based on templates. They can be used to contain data of the supported types CObject*,UINT, DWORD, and CString. You can use these predefined collections (such as CObList) to
hold collections of any objects derived from CObject. MFC also provides other predefined
collections to hold primitive types such as UINT and void pointers (void*). In general,
however, it is often useful to define your own type-safe collections to hold objects of a more
specific class and its derivatives. Note that doing so with the collection classes not based on
templates is more work than using the template-based classes.
There are two ways to create type-safe collections with the nontemplate collections:
1) Use the nontemplate collections, with type casting if necessary. This is the easiest
approach.
2) Derive from and extend a nontemplate type-safe collection.
To use the nontemplate collections with type casting.
Use one of the nontemplate classes, such as CWordArray, directly.
For example, you can create a CWordArray and add any 32-bit values to it, then retrieve
them. There is nothing more to do. You just use the predefined functionality.
You can also use a predefined collection, such as CObList, to hold any objects derived from
CObject. A CObList collection is defined to hold pointers to CObject. When you retrieve an
object from the list, you may have to cast the result to the proper type since the CObList
functions return pointers to CObject. For example, if you store CPerson objects in a CObList
collection, you have to cast a retrieved element to be a pointer to a CPerson object. The
following example uses a CObList collection to hold CPerson objects:
class CPerson : public CObject {...};
CPerson* p1 = new CPerson(...);
CObList myList;
myList.AddHead( p1 ); // No cast needed
CPerson* p2 = ( CPerson* )myList.GetHead();
This technique of using a predefined collection type and casting as necessary may be
adequate for many of your collection needs. If you need further functionality or more type
safety, use a template-based class, or read the next procedure.
To derive and extend a nontemplate type-safecollection
Derive your own collection class from one of the predefined nontemplate classes.
When you derive your class, you can add type-safe wrapper functions to provide a type-safe
interface to existing functions.
For example, if you derived a list from CObList to hold CPerson objects, you might add the
wrapper functions AddHeadPerson and GetHeadPerson, as shown below.
class CPersonList : public CObList
{
public:
void AddHeadPerson(CPerson* person){AddHead(person);}
SEED Infotech Ltd.
7/27/2019 7 Serialization and Collection Classesssdfsdf
13/18
Serialization and Collection Classes Page 107
const CPerson* GetHeadPerson()
{return (CPerson*)GetHead();}
};
These wrapper functions provide a type-safe way to add and retrieve CPerson objects from
the derived list. You can see that for the GetHeadPerson function, you are simply
encapsulating the type casting.
You can also add new functionality by defining new functions that extend the capabilities of
the collection rather than just wrapping existing functionality in type-safe wrappers. For
example, the article Collections: Deleting All Objects in a CObject Collection describes a
function to delete all the objects contained in a list. This function could be added to the
derived class as a member function.
The MFC array collection classes both template-based and not use indexes to access
their elements. The MFC list and map collection classes both template-based and not
use an indicator of type POSITION to describe a given position within the collection. To
access one or more members of these collections, you first initialize the position indicator and
then repeatedly pass that position to the collection and ask it to return the next element.The collection is not responsible for maintaining state information about the progress of the
iteration. That information is kept in the position indicator. But, given a particular position, the
collection is responsible for returning the next element.
Iterating an Collection class
Iterating an array
Iterating a list
Iterating a map
SEED Infotech Ltd.
7/27/2019 7 Serialization and Collection Classesssdfsdf
14/18
Page 108 Serialization and Collection Classes
To iterate an array
Use sequential index numbers with the GetAt member function:
CTypedPtrArray myArray;
for( int i = 0; i < myArray.GetSize();i++ )
{CPerson* thePerson = myArray.GetAt( i );
...
}
This example uses a typed pointer array that contains pointers to CPerson objects. The array
is derived from class CObArray, one of the nontemplate predefined classes. GetAt returns a
pointer to a CPerson object. For typed pointer collection classes arrays or lists the first
parameter specifies the base class; the second parameter specifies the type to store.
The CTypedPtrArray class also overloads the [] operator so that you can use the customary
array-subscript syntax to access elements of an array. An alternative to the statement in the
body of the for loop above is
CPerson* thePerson = myArray[ i ];
This operator exists in both const and non-const versions. The const version, which is
invoked forconst arrays, can appear only on the right side of an assignment statement.
To iterate a list
Use the member functions GetHeadPosition and GetNext to work your way through the list:
CTypedPtrList myList;POSITION pos = myList.GetHeadPosition();
while( pos != NULL )
{
CPerson* thePerson = myList.GetNext( pos );
...
}
This example uses a typed pointer list to contain pointers to CPerson objects.
To iterate a mapUse GetStartPosition to get to the beginning of the map and GetNextAssoc to repeatedly
get the next key and value from the map, as shown by the following example:
CMap myMap;
POSITION pos = myMap.GetStartPosition();
while( pos != NULL )
{
CPerson* pPerson;
CString string;
// Get key ( string ) and value ( pPerson )
myMap.GetNextAssoc( pos, string, pPerson );
// Use string and pPerson
}
SEED Infotech Ltd.
7/27/2019 7 Serialization and Collection Classesssdfsdf
15/18
Serialization and Collection Classes Page 109
This example uses a simple map template (rather than a typed pointer collection) that uses
CString keys and stores pointers to CPerson objects. When you use access functions such
as GetNextAssoc, the class provides pointers to CPerson objects. If you use one of the
nontemplate map collections instead, you must cast the returned CObject pointer to a pointer
to a CPerson.
NoteFor nontemplate maps, the compiler requires a reference to a CObject pointer in the last
parameter to GetNextAssoc. On input, you must cast your pointers to that type, as
shown in the next example.
The template solution is cleaner and provides better type safety. The nontemplate code is
more complicated, as you can see here:
CMapStringToOb myMap; //A nontemplate collection class
POSITION pos = myMap.GetStartPosition( );
while( pos != NULL ){
CPerson* pPerson;
CString string;
// Gets key (string) and value (pPerson)
myMap.GetNextAssoc(pos,string,(CObject*&)pPerson);
ASSERT(pPerson->IsKindOf(RUNTIME_CLASS(CPerson)));
// Use string and pPerson
}
Deleting Object in a Collection class
A list
An array
A map
To delete all objects in a list of pointers to CObject
3) Use GetHeadPosition and GetNext to iterate through the list.
4) Use the delete operator to delete each object as it is encountered in the iteration.
5) Call t he RemoveAll function to remove all elements from the list after the objects
associated with those elements have been deleted.The following example shows how to delete all objects from a list of CPerson objects. Each
object in the list is a pointer to a CPerson object that was originally allocated on the heap.
CTypedPtrList myList;
POSITION pos = myList.GetHeadPosition();
while( pos != NULL )
{
delete myList.GetNext( pos );
}
myList.RemoveAll();
The last function call, RemoveAll, is a list member function that removes all elements fromthe list. The member function RemoveAt removes a single element.
SEED Infotech Ltd.
7/27/2019 7 Serialization and Collection Classesssdfsdf
16/18
Page 110 Serialization and Collection Classes
Notice the difference between deleting an elements object and removing the element itself.
Removing an element from the list merely removes the lists reference to the object. The
object still exists in memory. When you delete an object, it ceases to exist and its memory is
reclaimed. Thus, it is important to remove an element immediately after the elements object
has been deleted so that the list wont try to access objects that no longer exist.
To delete all elements in an array
1) Use GetSize and integer index values to iterate through the array.
2) Use the delete operator to delete each element as it is encountered in the iteration.
3) Call the RemoveAll function to remove all elements from the array after they have been
deleted.
The code for deleting all elements of an array is as follows:
CArray myArray;
int i = 0;
while (i < myArray.GetSize() )
{delete myArray.GetAt( i++ );
}
myArray.RemoveAll();
Like the list example above, you can call RemoveAll to remove all elements in an array or
RemoveAt to remove an individual element.
To delete all elements in a map
1) Use GetStartPosition and GetNextAssoc to iterate through the array.
2) Use the delete operator to delete the key and/or value for each map element as it is
encountered in the iteration.
3) Call the RemoveAll function to remove all elements from the map after they have been
deleted.
The code for deleting all elements of a CMap collection is as follows. Each element in the
map has a string as the key and a CPerson object (derived from CObject) as the value.
CMap myMap;
// ... Add some key-value elements...
// Now delete the elements
POSITION pos = myMap.GetStartPosition();
while( pos != NULL )
{
CPerson* pPerson;
CString string;
// Gets key (string) and value (pPerson)
myMap.GetNextAssoc( pos, string, pPerson );
delete pPerson;
}
// RemoveAll deletes the keys
myMap.RemoveAll();
You can call RemoveAll to remove all elements in a map or RemoveKey to remove an
individual element with the specified key.
SEED Infotech Ltd.
7/27/2019 7 Serialization and Collection Classesssdfsdf
17/18
Serialization and Collection Classes Page 111
StacksBecause the standard list collection has both a head and a tail, it is easy to create a derived list
collection that mimics the behavior of a last-in-first-out (LIFO) stack. A stack is like a stack of trays
in a cafeteria. As trays are added to the stack, they go on top of the stack. The last tray added is
the first to be removed. The list collection member functions AddHead and RemoveHead can be
used to add and remove elements specifically from the head of the list; thus the most recentlyadded element is the first to be removed.
To create a stack collection
Derive a new list class from one of the existing MFC list classes and add more member
functions to support the functionality of stack operations.
The following example shows how to add member functions to push elements on to the stack,
peek at the top element of the stack, and pop the top element from the stack
class CTray : public CObject { ... };
class CStack : public CTypedPtrList< CObList, CTray* >{
public:
// Add element to top of stack
void Push( CTray* newTray )
{ AddHead( newTray ); }
// Peek at top element of stack
CTray* Peek()
{ return IsEmpty() ? NULL : GetHead(); }
// Pop top element off stack
CTray* Pop()
{ return RemoveHead(); }
};
Note that this approach exposes the underlying CObList class. The user can call any
CObList member function, whether it makes sense for a stack or not.
QueuesBecause the standard list collection has both a head and a tail, it is also easy to create a derived
list collection that mimics the behavior of a first-in-first-out queue. A queue is like a line of people
in a cafeteria. The first person in line is the first to be served. As more people come, they go to
the end of the line to wait their turn. The list collection member functions AddTail and
RemoveHead can be used to add and remove elements specifically from the head or tail of thelist; thus the most recently added element is always the last to be removed.
To create a queue collection
Derive a new list class from one of the predefined list classes provided with the Microsoft
Foundation Class Library and add more member functions to support the semantics of queue
operations.
SEED Infotech Ltd.
7/27/2019 7 Serialization and Collection Classesssdfsdf
18/18
Page 112 Serialization and Collection Classes
The following example shows how you can append member functions to add an element to
the end of the queue and get the element from the front of the queue.
class CPerson : public CObject { ... };
class CQueue:public CTypedPtrList< CObList, CPerson* >
{
public:// Go to the end of the line
void AddToEnd( CPerson* newPerson )
{ AddTail( newPerson ); } // End of the queue
// Get first element in line
CPerson* GetFromFront()
{ return IsEmpty() ? NULL : RemoveHead(); }
};
Summary
Serialization is the process of writing or reading an object to or from a persistentstorage medium, such as a disk file.
MFC supplies built-in support for serialization in the class CObject.
MFC uses an object of the CArchive class as an intermediary between the object
to be serialized and the storage medium.
A CArchive object uses overloaded insertion () operators
to perform writing and reading operations.
MFC supplies two kinds of collection classes
Collection classes based on templates
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
Quiz3) What is serialization?
4) Which are the classes involved in serialization?
5) What are the five main steps to make a class serializable?
6) What is the significance of schema number in serialization?
7) How to iterate an collection class (CArray, CList, CMap)?
8) How to delete object from collection class (CArray, CList, CMap)?
SEED Infotech Ltd.