MFC CArchive Serialize 序列化类 设计和使用

序列化的出发点在于,一个对象的当前状态应该可以永久地存储起来,这些当前状态主要用它的成员变量来表示。然后,这个对象可以通过读取文件或者反串行化重新构造出来。序列化包含了处理所有对象指针细节以及在序列化对象过程中使用的对象的循环引用。序列化的一个关键点在于一个对象负责自己状态的读写,因此,一个可序列化的类必须实现基本的序列化操作。就像在序列化系列文章中看到的,在一个类中加上序列化功能的过程是不复杂的。MFC把CArchive 类作为了要序列化对象与存储介质之间的桥接者。CArchive 类对象总是与一个CFile对象联系在一起(CFile文件可能是一个磁盘文件也可能是一个内存文件,也可能是一个剪贴板文件!),从CFile对象中,CArchive 类对象可以获得必要的序列化信息,这其中包括保存文件名和要进行的操作是读还是写。一个对象可以使用CArchive对象进行序列化操作,这个过程是存储介质无关的。


一、设计一个可序列化类的五个步骤:

  1. 从CObject类派生出自己的类
  2. 重载Serialize()函数
  3. 在类的申明中使用DECLARE_SERIAL 宏
  4. 定义一个无参数的构造函数(重建对象的时候要用)
  5. 在类的实现文件中添加IMPLEMENT_SERIAL宏

如果你直接使用Serialize()函数,并不使用CArchive的<<和>>操作符,就可以省去后面的3步。

一个实例如下:一个CPerson类,有两个数据成员
class CPerson : public CObject 1  { public:    DECLARE_SERIAL( CPerson ) 3    // empty constructor is necessary    CPerson(){}; 4    CString m_name;    WORD   m_number;    void Serialize( CArchive& archive ); 2       // rest of class declaration };
以下添加在.cpp文件中
IMPLEMENT_SERIAL( CPerson, CObject, 1 ) 5
void CPerson::Serialize( CArchive& archive ) {    // call base class function first    // base class is CObject in this case
    CObject::Serialize( archive );    // now do the stuff for our specific class    if( archive.IsStoring() )        archive << m_name << m_number;    else        archive >> m_name >> m_number; }

IMPLEMENT_SERIAL宏中的前两个参数很容易理解了,第三个参数是一个版本码,当将数据读到内存中的时候,系统会去检查这个版本码,如果磁盘和内存中的版本码不同,系统就会抛出一个CArchiveException异常,防止你的程序读到不正确的对象数据版本。
备注:解决读多个版本数据问题!!!
二、创建一个CArchive对象
 创建一个CAchive对象有两种方式:1.使用MFC的document/View框架中内的Serialize函数,这称为隐式创建。2.显示创建就是直接申明一个与CFile对象相关联的对象。
  隐式方法就是直接使用框架中CMyDocument类的Serialize(),这里要强调的是,如果CMyDocumen-t中有内嵌的类成员,那么,这个类也应该是有串行化能力的,否则用户要自己加上这个功能;怎么创建一个可串行化的类在上面已经讲的很清楚了!显示创建的方法步骤如下:
 1.打开一个另存为的对话框,获取文件名称
 2.申明一个CFile对象打开这个文件
 3.申明一个CArchive对象,关联这个CFile对象
 4.调用Serialize()函数,将这个CArchive对象作为参数传递
说得很抽象,以下是一个具体的例子:
    
    
    
    
const char szFilter[] = "MIMA Files (*.cy)|*.cy|; *.cy||";
        CFileDialog fileDlg(false,".cy","mmmanager",OFN_HIDEREADONLY|OFN_OVERWRITEP ROMPT,szFilter); 1
        CString strFileName;
        CFile file;
        if(IDOK == fileDlg.DoModal())
        {
            strFileName = fileDlg.GetFileName();
            file.Open(strFileName,CFile::modeCreate | CFile::modeWrite); 2
            CArchive ar(&file,CArchive::store); 3
            m_objMM.Serialize(ar); 4
        }
第四步中要指出的是,这个Serialize()函数只要能在此调用就可以,不管是谁的。
一般的Serialize()函数模板长这个样子:
void CPerson::Serialize(CArchive& ar) {    CObject::Serialize(ar);    if (ar.IsStoring())    {        // TODO:  add storing code here
 ar<<....
    }    else    {    // TODO:  add loading code here
 ar>>...
   }
}
三、串行化CObject对象
 <<和>>操作符只用于一些简单的数据类型,要是串行化一个对象(或者对象的指针),就直接使用这个对象的Serialize()函数。

你可能感兴趣的:(mfc,Serialize,CArchive,序列化串行化)