Wednesday, November 26, 2008

Advantages of deriving a class from CObject.

CObject - The principal base class for the Microsoft Foundation Class Library.
CObject provides basic services, including Serialization support

·         Run-time class information

·         Object diagnostic output // using virtual void Dump(  CDumpContext& dc ) const;

·         Compatibility with collection classes //MFC collection classes using CObject as parameter.

 

CObject Members

Diagnostics

 

  virtual void AssertValid( ) const;

Validates this object's integrity.

  virtual void Dump( CDumpContext& dc ) const;

Produces a diagnostic dump of this object.

Serialization

 

  BOOL IsSerializable( ) const;

Tests to see whether this object can be serialized.

  virtual void Serialize(   CArchive& ar );

Loads or stores an object from/to an archive.

Miscellaneous

 

  virtual CRuntimeClass* GetRuntimeClass( ) const;

Returns the CRuntimeClass structure corresponding to this object's class.

  BOOL IsKindOf( const CRuntimeClass* pClass ) const;

Tests this object's relationship to a given class.

 

You can choose from four levels of functionality when deriving a class from CObject:
    
1: Diagnostic memory management
           
No macro just derive from CObject.
            Override  
void AssertValid() and void Dump(CDumpContext& dc);
      
We can use Diagnostic Dumping With the help of afxDump object.
            Example : afxDump << myObject.
            Note: Automatic Dump of Undeleted Objects is done by the framework. There is no relation with
           
CObject::Dump.

    2:  Support for run-time class information
           
DECLARE_DYNAMIC(class_name)   in Header file and IMPLEMENT_DYNAMIC(class_name,
            
base_class_name) included in the class implementation(.cpp).
            You can then use the RUNTIME_CLASS macro and the CObject::IsKindOf function to determine the class of
            your objects at run time.
     3:
Support for run-time class information and dynamic creation
           
DECLARE_DYNCREATE(class_name)         IMPLEMENT_DYNCREATE(class_name, base_class_name)
            Object can be created dynamically using
           
CObject* CreateObject();
       static CObject* PASCAL CreateObject(  LPCSTR lpszClassName );
       static CObject* PASCAL CreateObject(  LPCWSTR lpszClassName);
      
Support for run-time class information, dynamic creation, and serialization
           
DECLARE_SERIAL(class_name)       IMPLEMENT_SERIAL (class_name, base_class_name, wSchema)
Note: Above macros are applicable to only CObject’s derived class.
If you implement case 2 there is no need to implement case 1.(compiler error)
If you implement case 3 there is no need to implement case 1 and case 2.

Sample source code.

#pragma once
// CMyObject command target
class CMyObject : public CObject
{
      DECLARE_SERIAL(CMyObject)
public:
      CMyObject();
      virtual ~CMyObject();
      virtual void Serialize(CArchive& ar);
      //get and Set
      inline __int64& PhoneNumber()
      {
            return m_nPhoneNumber;
      }
      //only Get
      inline CString& Name()
      {
            return m_strName;
      }
#ifdef _DEBUG
      virtual void AssertValid() const;
#ifndef _WIN32_WCE
      virtual void Dump(CDumpContext& dc) const;
#endif
#endif
      //Private member variables.
      __int64 m_nPhoneNumber;
      CString m_strName;
};

// MyObject.cpp : implementation file
#include "stdafx.h"
#include "MyObject.h"
#define new DEBUG_NEW //Assists in finding memory leaks.
// CMyObject
IMPLEMENT_SERIAL( CMyObject, CObject,  VERSIONABLE_SCHEMA | 1 )
CMyObject::CMyObject()
{
      m_nPhoneNumber = -1;
      m_strName = _T("Sen SD");
}
CMyObject::~CMyObject()
{
}

// CMyObject member functions
void CMyObject::Serialize(CArchive& ar)
{
      if (ar.IsLoading())
      {
            ////it is not working I don't know.
            // will not work for direct call of Serialize.
            UINT nVersion = ar.GetObjectSchema();
            switch(nVersion)
            {
            case -1:
                  //version Unknown.
                  ar >> m_nPhoneNumber;//call Current version's deserialize code.
                  ar >> m_strName;
                  break;
            case 0:
                  // read in previous version of  this object
                  break;
            case 1:
                  //Current version.
                  ar >> m_nPhoneNumber;
                  ar >> m_strName;
                  break;
            default:
                  // report unknown version of
                  // this object
                  break;
            }
      }
      else
      {
            ar << m_nPhoneNumber;
            ar << m_strName;
      }
}
#ifdef _DEBUG
void CMyObject::AssertValid() const
{
      __super::AssertValid();
}
#ifndef _WIN32_WCE
void CMyObject::Dump(CDumpContext& dc) const
{
      __super::Dump(dc);// Displays the class name.
      dc << "Phone Number : " << m_nPhoneNumber << "\n";
      dc << "Name         : " << m_strName << "\n";
}
#endif
#endif //_DEBUG

Sample code How to use CMyObject class.

void CTestMfcDlg::TestStart()
{
      CMyObject* pMyObject = (CMyObject*) CRuntimeClass::CreateObject(_T("CMyObject"));
      BOOL isKind = pMyObject->IsKindOf(RUNTIME_CLASS( CMyObject));
      pMyObject->PhoneNumber() = 9846000000;

#ifdef _DEBUG
      afxDump << pMyObject;
#endif //_DEBUG
      ::WriteObject( _T("C:\\CMyObject.arc"), pMyObject);
      delete pMyObject;

      CMyObject* pReadMyObject = ::ReadObject( _T("C:\\CMyObject.arc"));
      afxDump << pReadMyObject;
#ifdef _DEBUG
      delete pReadMyObject;
#endif //_DEBUG
}

CMyObject* ReadObject( const CString& strFilePath)
{
      CFile readingFile( strFilePath,CFile::modeRead);
      CArchive readingArchive(&readingFile,CArchive::load);
      CMyObject *pFileObject = new CMyObject();
      pFileObject->Serialize( readingArchive);
      readingFile.Close();
      readingArchive.Close();
      return pFileObject;
}
void WriteObject( const CString& strFilePath, CMyObject *pObj)
{
      CFile storingFile( strFilePath,CFile::modeCreate | CFile::modeWrite);
      CArchive storingArchive(&storingFile,CArchive::store);
      pObj->Serialize( storingArchive);
      storingArchive.Close();
      storingFile.Close();
}

 

 

 

 

No comments: