📄 chap7_4.htm
字号:
<html><head><meta http-equiv="Content-Type"content="text/html; charset=gb_2312-80"><meta name="GENERATOR" content="Microsoft FrontPage Express 2.0"><title>7.4 定制串行化</title><link rel="stylesheet" href="../../../cpcw.css"></head><body link="#3973DE" alink="#3973DE" background="../../bg.gif"><div align="center"><center><table border="0" cellpadding="0" cellspacing="0" width="85%"> <tr bgcolor="#FFFFFF"> <td> <div align="center"><center><table border="0" cellpadding="0" cellspacing="0" width="615" height="20"> </table> </center></div> <p align="center"><font color="#FF3333" face="Times New Roman"><b>7.4</b></font><b><font color="#3973DE" size="4" face="Times New Roman"> </font><font color=red>定制串行化</font></b></p> <p><font > 前面编辑器的例子使用</font><font face="Times New Roman">CString</font><font >类的字符串来保存文本行,由于它是</font><font face="Times New Roman">MFC</font><font >类,因此可以串行化自己,将自己写入磁盘或从磁盘文件中读取二进制数据来建立对象。那么,如果不是标准的</font><font face="Times New Roman">MFC</font><font >类,比如用户自己定义的类,如何让它支持串行化呢?下面,我们结合前面第五章提到的就业调查表的例子来演示如何让用户定义的类支持串行化功能。</font></p> <p><font > 要让用户定义的类支持串行化,一般分为五步:</font></p> <p><font face="Times New Roman">1.</font><font >从</font><font face="Times New Roman">CObject</font><font >或其派生类派生出用户的类</font></p> <p><font face="Times New Roman">2.</font><font >重载</font><font face="Times New Roman">Serialize()</font><font >成员函数,加入必要的代码,用以保存对象的数据成员到</font><font face="Times New Roman">CArchive</font><font >对象以及从</font><font face="Times New Roman">CArchive</font><font >对象载入对象的数据成员状态。</font></p> <p><font face="Times New Roman">3.</font><font >在类声明文件中,加入</font><font face="Times New Roman">DECLARE_SERIAL</font><font >宏。编译时,编译器将扩充该宏,这是串行化对象所必需的。</font></p> <p><font face="Times New Roman">4.</font><font >定义一个不带参数的构造函数。</font></p> <p><font face="Times New Roman">5.</font><font >在实现文件中加入</font><font face="Times New Roman">IMPLEMENT_SERIAL</font><font >宏。</font></p> <p><font face="Times New Roman">class CRegister:public CObject</font></p> <p><font face="Times New Roman">{</font></p> <blockquote> <p><font size="2" face="Courier New">public:</font></p> </blockquote> <p><font size="2" face="Courier New">DECLARE_SERIAL( CRegister)</font></p> <p><font face="Courier New">//</font><font >必需提供一个不带任何参数的空的构造函数</font></p> <blockquote> <p><font size="2" face="Courier New">CRegister(){};</font></p> </blockquote> <p><font face="Times New Roman">public:</font></p> <p><font face="Times New Roman">CString strIncome;</font></p> <p><font face="Times New Roman">CString strKind;</font></p> <p><font face="Times New Roman">BOOL bMarried;</font></p> <p><font face="Times New Roman">CString strName;</font></p> <p><font face="Times New Roman">int nSex;</font></p> <p><font face="Times New Roman">CString strUnit;</font></p> <p><font face="Times New Roman">int nWork;</font></p> <p><font face="Times New Roman">UINT nAge;</font></p> <p><font face="Times New Roman">void Serialize(CArchive&);</font></p> <p><font face="Times New Roman">};</font></p> <p><font face="Times New Roman"> MFC</font><font >在从磁盘文件载入对象状态并重建对象时,需要有一个缺省的不带任何参数的构造函数。串行化对象将用该构造函数生成一个对象,然后调用</font><font face="Times New Roman">Serialize()</font><font >函数,用重建对象所需的值来填充对象的所有数据成员变量。</font></p> <p><font > 构造函数可以声明为</font><font face="Times New Roman">public</font><font >、</font><font face="Times New Roman">protected</font><font >或</font><font face="Times New Roman">private</font><font >。如果使它成为</font><font face="Times New Roman">protect</font><font >或</font><font face="Times New Roman">private</font><font >,则可以确保它只被串行化过程所使用。</font></p> <p><font > 在类定义文件中给出</font><font face="Times New Roman">Serialize()</font><font >的定义。它包括对象的保存和载入两部分。前面已经提到,</font><font face="Times New Roman">CArchive</font><font >类提供一个</font><font face="Times New Roman">IsStoring()</font><font >成员函数指示是保存数据到磁盘文件还是从磁盘文件载入对象。</font></p> <p><font face="Times New Roman">void CRegister::Serialize(CArchive& ar)</font></p> <p><font face="Times New Roman">{</font></p> <p><font face="Courier New">//</font><font >首先调用基类的</font><font face="Courier New">Serialize()</font><font >方法。</font></p> <p><font size="2" face="Courier New">CObject::Serialize( ar);</font></p> <p><font face="Times New Roman">if(ar.IsStoring())</font></p> <p><font face="Times New Roman">{</font></p> <p><font face="Times New Roman">ar<<strIncome;</font></p> <p><font face="Times New Roman">ar<<strKind;</font></p> <p><font face="Times New Roman">ar<<(int)bMarried;</font></p> <p><font face="Times New Roman">ar<<strName;</font></p> <p><font face="Times New Roman">ar<<nSez;</font></p> <p><font face="Times New Roman">ar<<strUnit;</font></p> <p><font face="Times New Roman">ar<<nWork;</font></p> <p><font face="Times New Roman">ar<<(WORD)nAge;</font></p> <p><font face="Times New Roman">}</font></p> <p><font face="Times New Roman">else</font></p> <p><font face="Times New Roman">{</font></p> <p><font face="Times New Roman">ar>>strIncome;</font></p> <p><font face="Times New Roman">ar>>strKind;</font></p> <p><font face="Times New Roman">ar>>(int)bMarried;</font></p> <p><font face="Times New Roman">ar>>strName;</font></p> <p><font face="Times New Roman">ar>>nSex;</font></p> <p><font face="Times New Roman">ar>>strUnit;</font></p> <p><font face="Times New Roman">ar>>nWork;</font></p> <p><font face="Times New Roman">ar>>(WORD)nAge;</font></p> <p><font face="Times New Roman">}</font></p> <p><font face="Times New Roman">}</font></p> <p><font > 我们看到,对象的串行化实际上是通过调用对象中的数据成员的串行化来完成的。</font></p> <div align="center"><center><table border="2" cellpadding="2" cellspacing="0" width="100%" bgcolor="#80D6FF"> <tr> <td width="100%"><font >注意</font><font face="Times New Roman">:CArchive</font><font >类的</font><font face="Times New Roman">>></font><font >和</font><font face="Times New Roman"><<</font><font >操作符并不支持所有的标准数据类型。它支持的数据类型有:</font><font face="Times New Roman">CObject</font><font >、</font><font face="Times New Roman">BYTE</font><font >、</font><font face="Times New Roman">WORD</font><font >、</font><font face="Times New Roman">int</font><font >、</font><font face="Times New Roman">LONG</font><font >、</font><font face="Times New Roman">DWORD</font><font >、</font><font face="Times New Roman">float</font><font >和</font><font face="Times New Roman">double</font><font >。其他的类型的数据要进行串行化输入输出时,需要将该类型的数据转化为上述几种类型之一方可。</font></td> </tr> </table> </center></div> <p><font ><br> 另外,在类的实现(类定义)文件开始处,还要加入</font><font face="Times New Roman">IMPLEMENT_SERIAL</font><font >宏。</font></p> <blockquote> <p><font face="Times New Roman">IMPLEMENT_SERIAL( CRegister, CObject, 1 )</font></p> </blockquote> <p><font face="Times New Roman"> IMPLEMENT_SERIAL</font><font >宏用于定义一个从</font><font face="Times New Roman">CObject</font><font >派生的可串行化类的各种函数。宏的第一和第二个参数分别代表可串行化的类名和该类的直接基类。</font></p> <p><font > 第三个参数是对象的版本号,它是一个大于或等于零的整数。</font><font face="Times New Roman">MFC</font><font >串行化代码在将对象读入内存时检查版本号。如果磁盘文件上的对象的版本号和内存中的对象的版本号不一致,</font><font face="Times New Roman">MFC</font><font >将抛出一个</font><font face="Times New Roman">CArchiveException</font><font >异常,阻止程序读入一个不匹配版本的对象。</font></p> <p><font > 现在,我们就可以象使用标准</font><font face="Times New Roman">MFC</font><font >类一样使用</font><font face="Times New Roman">CRegister</font><font >的串行化功能了。</font></p> <p><font face="Times New Roman">CArchive ar;</font></p> <p><font face="Times New Roman">CRegister reg1,reg2;</font></p> <p><font face="Times New Roman">ar<<reg1<<reg2;</font></p> <p><font > 读者请试着在第五章职工调查表程序基础上,增加保存调查信息到文件以及从文件中读入调查表信息功能。对于多个调查表,可考虑采用</font><font face="Times New Roman">CObjList</font><font >链表保存多个对象的指针。</font></p> <p><font > 串行化简化了对象的保存和载入,为对象提供了持续性。但是,串行化本身还是具有一定的局限性的。串行化一次从文件中载入所有对象,这不适合于大文件编辑器和数据库。对于数据库和大文件编辑器,它们每次只是从文件中读入一部分。此时,就要避开文档的串行化机制来直接读取和保存文件了。另外,使用外部文件格式(预先定义的文件格式而不是本应用程序定义的文件格式)的程序一般也不使用文档的串行化。下面我们就给出这样一个例子,说明在不使用串行化情况下如何读取和保存文件。</font></p> <div align="center"><center><table border="0" cellpadding="0" cellspacing="0" width="615"> <tr> <td><a href="chap7_3.htm">上一页</a></td> <td><p align="right"><a href="chap7_5.htm">下一页</a></p> </td> </tr> </table> </center></div><hr size="1" noshade color="#3973DE"> </td> </tr></table></center></div><p align="center"><font size="5"></font> </p><p><font ><b></b></font> </p><p><font ></font> </p><p> </p></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -