MFC串行化原理

 

MFC串行化原理

作者:flyfish 2014-2-8

简介

  本文章源码分析MFC的版本是10.0(VC2010)

串行化Serialization简单说就是在程序中定义的对象转换成连续的字节数据,无论这种连续的字节数据是在内存还是存储在硬盘上。程序重启之后,读取硬盘的数据,可以根据硬盘上的数据生成一个新的对象。

 

数据的读写

CArchive类

串行化的前提

从获取的文件信息中生成一个的对象首先需要知道类的信息,知道类的信息以后还需要动态创建,所以串行化的前提就是

1运行时类型识别 RTTI RuntimeType Identification的缩写

2 动态创建

CRuntimeClass获取对象运行时类型信息和动态创建对象

 

对象的串行化示例代码

要使自己的类支持串行化功能时

首先创建一个继承自CObject 类

 

class CTest : public CObject

{

protected:

 DECLARE_SERIAL(CTest);

public:

virtual void Serialize(CArchive& ar);

}

 

IMPLEMENT_SERIAL(CTest, CObject,0|VERSIONABLE_SCHEMA)

 

CObject ,CRuntimeClass, CArchive是MFC重要的三个类

CObject类的实现在文件objcore.cpp文件

CRuntimeClass结构和CArchive类的实现在arccore.cpp文件

 

CRuntimeClass类

 

动态创建 由CRuntimeClass的静态成员函数CreateObject提供,

 

存储类的信息包括类名,类的版本,类的继承关系等都是由CRuntimeClass实现的

该类位于afx.h文件中第422行的CRuntimeClass结构

struct CRuntimeClass

{

// Attributes

    LPCSTRm_lpszClassName;

    int m_nObjectSize;

    UINTm_wSchema; // schema number of the loaded class

    CObject*(PASCAL* m_pfnCreateObject)(); // NULL => abstractclass

#ifdef _AFXDLL

    CRuntimeClass*(PASCAL* m_pfnGetBaseClass)();

#else

    CRuntimeClass*m_pBaseClass;

#endif

 

// Operations

    CObject*CreateObject();

    BOOLIsDerivedFrom(const CRuntimeClass* pBaseClass) const;

 

    // dynamic name lookup and creation

    static CRuntimeClass* PASCAL FromName(LPCSTRlpszClassName);

    static CRuntimeClass* PASCAL FromName(LPCWSTRlpszClassName);

    static CObject* PASCAL CreateObject(LPCSTRlpszClassName);

    static CObject* PASCAL CreateObject(LPCWSTRlpszClassName);

 

// Implementation

    void Store(CArchive& ar) const;

    static CRuntimeClass* PASCAL Load(CArchive& ar,UINT* pwSchemaNum);

 

    // CRuntimeClass objects linked together in simple list

    CRuntimeClass*m_pNextClass;       // linked list of registered classes

    const AFX_CLASSINIT* m_pClassInit;

};

 

CreateObject函数正是动态创建对象,因为该函数是全局使用所以使用了Static声明,

全局使用时语法是 类名::函数名(CreateObject)

两个CreateObject函数,一个处理多字节,一个处理Unicode 

 

示例代码中使用的宏

DECLARE_SERIAL宏位于afx.h文件中的627行

#define DECLARE_SERIAL(class_name) …

 

IMPLEMENT_SERIAL宏 位于afx.h文件中的680行

#define IMPLEMENT_SERIAL(class_name, base_class_name, wSchema) …

 

正是DECLARE_SERIAL和IMPLEMENT_SERIAL这两个宏实现了动态创建对象

该宏封装了CRuntimeClass的CreateObject

 

整个CRuntimeClass对象构成了一简单的列表,指针都存储在m_classList中,该列表类是CTypedSimpleList

由m_pNextClass指针指向下一个CRuntimeClass结构

由m_pBaseClass指针确定类的继承关系

 

FromName函数就是一个遍历m_classList,进行字符串比较

 

CTypedSimpleList类位于afxtls_.h 79行

因为处理对象之前还要处理类版本号,类名长度等,所以CRuntimeClass 拥有Load函数和Store函数

void CRuntimeClass::Store(CArchive& ar) const

    // stores a runtime class description

{

    WORD nLen =(WORD)lstrlenA(m_lpszClassName);

    ar <<(WORD)m_wSchema << nLen;

    ar.Write(m_lpszClassName,nLen*sizeof(char));

}

 

CRuntimeClass* PASCALCRuntimeClass::Load(CArchive& ar, UINT* pwSchemaNum)

    // loads a runtime class description

{

代码位于arccore.cpp文件的183行

}

 

CArchive类

wSchema的作用区分类版本,通过CArchive读写对象。

GetObjectSchema是获取CRuntimeClass中类的wSchema版本信息

CArchive重载<<和>> 操作符读写各种类型的对象声明代码位于afx.h 1580行

 

CObject类

 

IsKindOf实现了类型识别功能

遍历列表中的元素与参数指定的某个CRuntimeClass对象比较,存在则返回TRUE

BOOL CObject::IsKindOf(const CRuntimeClass* pClass) const

IsKindOf调用CRuntimeClass类的IsDerivedFrom函数

 

BOOL CRuntimeClass::IsDerivedFrom(const CRuntimeClass* pBaseClass) const

{

代码位于objcore.cpp文件的165行

}


最终形成了如下宏

运行时类识别

DECLARE_DYNAMIC

IMPLEMENT_DYNAMIC

 

动态创建

DECLARE_DYNCREATE

IMPLEMENT_DYNCREATE

 

串行化

DECLARE_SERIAL

IMPLEMENT_SERIAL

 

你可能感兴趣的:(mfc,串行化)