7 serialization and collection classesssdfsdf

Upload: sangeethaag19

Post on 14-Apr-2018

221 views

Category:

Documents


0 download

TRANSCRIPT

  • 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.