步骤
我们知道CArchive类可以支持基本类型的串行化,还可以支持派生于CObject类的派生类,想要这个派生类支持可串行化,需要如下步骤即可:
(1) 从CObject类派生或者从CObject类派生的某个派生类
(2) 重写Serialize成员函数,把类的数据成员写入文件。
(3) 在类声明中使用“DECLARE_SERIAL”宏
(4) 定义不带参数的构造函数
(5) 在类的实现文件中使用“IMPLEMENT_SERIAL”宏
关于SERIAL宏
IMPLEMENT_SERIAL的形式如下:
IMPLEMENT_SERIAL( class_name, base_class_name, wSchema )
参数:
class_name 类的实际名字(不用引号括起来)。
base_class_name 基类的名字(不用引号括起来)。
wSchema 一个UINT类型的版本号。
DECLARE_SERIAL的形式如下:
DECLARE_SERIAL(class_name)
参数:
class_name 类的实际名字
这两个宏都是为动态的CObject派生类对象生成必要的C++代码,包括加载数据数据使new对象等操作。
实例
下面我们将“图形重绘和保存”这篇博文的CGraph对象串行化,使之我们能够永久保证数据对象,其具体串行化关键代码如下:
//Graph.h
//(1)派生于CObject类
class CGraph:public CObject
{
public:
//(3)声明中使用DECLARE_SERIAL宏
DECLARE_SERIAL(CGraph)
//(4)定义无参的构造函数
CGraph(void);
CGraph(CPoint ptBegin, CPoint ptEnd, int DrawType);
~CGraph(void);
//(2)重写Serialize成员函数
virtual void Serialize(CArchive& ar);
...
private:
CPoint m_ptBegin;
CPoint m_ptEnd;
int m_DrawType;
};
#include "StdAfx.h"
#include "Graph.h"
//(5)实现文件中使用“IMPLEMENT_SERIAL”宏
IMPLEMENT_SERIAL(CGraph, CObject, 1)
CGraph::CGraph(void)
{
m_DrawType = 0;
}
//Call 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.
void CGraph::Serialize(CArchive& ar)
{
// call base class function first
// base class is CObject in this case
CObject::Serialize(ar);
// now do the stuff for our specific class
if (ar.IsStoring())//保存文件时执行
{
ar << m_DrawType << m_ptBegin << m_ptEnd;
}
else
{
ar >> m_DrawType >> m_ptBegin >> m_ptEnd;//加载时数据从硬盘中加载到内存
}
}
我们在提取和插入类对象时,需要使用指针对象,形如:
CGraph *pGraph;
ar << pGraph;//保存数据
ar >> pGraph;//提取数据
实现重绘和保存的基本原理
1.点击保存时,Document类将内存中的绘图参数信息写到指定的文件名,从而永久性的保存;
2.点击打开时,Document类将从指定文本中加载CGraph参数信息到指定指针变量,当数据加载全部完成后,View中的OnDraw虚函数中负责图形重新显示,即调用CGraph的DrawItem接口完成图形重绘。
实例代码下载地址:
http://download.youkuaiyun.com/download/xiao3404/9886827