MFC通过将类信息写入到文件,再从文件中动态将类创建出来,即为持久化。动态创建是持久化的基础,持久化包含了动态创建的全部功能。
使用持久化特性,需要以下四个条件:
1、从CObject派生
2、提供不带参数的默认构造参数
3、在类声明中添加DECLARE_SERIAL宏,在实现体中添加IMPLEMENT_SERIAL宏。
4、重载Serialize函数
一个示例:
private:
int m_nCnt;
};
IMPLEMENT_SERIAL(CMyClass, CObject, 1);
// 宏展开
class CMyClass : public CObject
{
public:
static const CRuntimeClass classCMyClass;
virtual CRuntimeClass* GetRuntimeClass() const;
static CObject* PASCAL CreateObject();
friend CArchive& AFXAPI operator>>(CArchive& ar, CMyClass* &pOb);
public:
CMyClass(int n = 10) : m_nCnt(n) { }
virtual void Serialize(CArchive& ar);
private:
int m_nCnt;
};
CObject* PASCAL CMyClass::CreateObject()
{ return new CMyClass; }
extern AFX_CLASSINIT _init_CMyClass;
const CRuntimeClass CMyClass::classCMyClass = {
"CMyClass", sizeof(class CMyClass), 1, CMyClass::CreateObject,
RUNTIME_CLASS(CObject), NULL, _init_CMyClass };
AFX_CLASSINIT _init_CMyClass(RUNTIME_CLASS(CMyClass)); // 该全局变量,将类添加到进程类链表中,同时更新了CRuntimeClass::m_pNextClass。
CArchive& AFXAPI operator>>(CArchive& ar, CMyClass* &pOb)
{
pOb = (CMyClass*) ar.ReadObject(RUNTIME_CLASS(CMyClass));
return ar;
}
到这里,CMyClass类有两个十分强大的功能。
1、根据类名称创建类。
CObject* PASCAL CRuntimeClass::CreateObject(LPCSTR lpszClassName)
{
// 通过CRuntimeClass::FromName函数查找类的CRuntimeClass指针.
CRuntimeClass* pClass = FromName(lpszClassName);
if (pClass == NULL)
{
return NULL;
}
// 通过CRuntimeClass::CreateObject()函数创建类,它进而通过函数指针m_pfnCreateObject创建类。
CObject* pObject = pClass->CreateObject();
return pObject;
}
CRuntimeClass* PASCAL CRuntimeClass::FromName(LPCSTR lpszClassName)
{
CRuntimeClass* pClass=NULL;
AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
AfxLockGlobals(CRIT_RUNTIMECLASSLIST);
// 在_init_CMyClass定义时,AfxClassInit函数已经将类的CRuntimeClass插入到了m_classList类链表中
for (pClass = pModuleState->m_classList; pClass != NULL;
pClass = pClass->m_pNextClass)
{
if (lstrcmpA(lpszClassName, pClass->m_lpszClassName) == 0)
{
AfxUnlockGlobals(CRIT_RUNTIMECLASSLIST);
return pClass;
}
}
AfxUnlockGlobals(CRIT_RUNTIMECLASSLIST);
return NULL; // not found
}
2、序列化
CArchive arOut(&file, CArchive::store);
CMyClass* pMyClass1 = new CMyClass(2000);
// 写入到文件,使用 AFX.INL 中统一的函数
// CArchive& AFXAPI operator<<(CArchive& ar, const CObject* pOb)
arOut<<pMyClass1;
arOut.Close();
file.SeekToBegin();
CArchive arIn(&file, CArchive::load);
CMyClass* pMyClass2 = NULL;
// 从文件中将读取类对象,操作符>>在宏中已经实现了重载
arIn>>pMyClass2;
arIn.Close();
file.Close();