17.2 序列化文档
所有这些听起来虽然相当棘手,但是序列化文档的基本功能已经完全由Application Wizard内置到应用程序中。File | Save、File | Save As和File | Open菜单项的处理程序都假定您想对文档实现序列化,并且已经包含了支持序列化的代码。下面将分析CSketcherDoc类的定义和实现中有关使用序列化创建文档的部分内容。
17.2.1 文档类定义中的序列化
CSketcherDoc类定义中支持文档对象序列化的代码在下列代码段中以粗体显示:
- class CSketcherDoc : public CDocument
- {
- protected: // create from serialization only
- CSketcherDoc();
- DECLARE_DYNCREATE(CSketcherDoc)
- // Rest of the class...
- // Overrides
- public:
- virtual BOOL OnNewDocument();
- virtual void Serialize(CArchive& ar);
- // Rest of the class...
- };
其中有3个部分与序列化文档对象有关:
(1) DECLARE_DYNCREATE()宏
(2) Serialize()成员函数
(3) 默认的类构造函数
DECLARE_DYNCREATE()宏在序列化输入过程中,支持应用程序框架动态地创建CSketcherDoc类的对象。在类实现中,有一个互补宏IMPLEMENT_DYNCREATE()与它配合使用。这些宏只应用于CObject派生的类,但是我们很快将看到,它们并非唯一一对可以在这种上下文中使用的宏。对于所有要序列化的类来说,CObject都必须是直接或间接基类,因为它将添加支持序列化操作的功能。这就是CElement类派生于CObject的原因。几乎所有MFC类都是派生于CObject,因此,它们都是可序列化的。
在Visual C++(www.cppentry.com)的MFC参考中,层次结构图列出了不是从CObject派生的类。注意CArchive在这个列表中。
在CSketcherDoc类定义中还包括虚函数Serialize()的声明。每个可序列化的类都必须包括这个函数。调用它时将对CSketcherDoc类的数据成员执行输入和输出序列化操作。作为参数传递给这个函数的CArchive类对象确定将要发生的操作是输入还是输出。在讨论对文档类实现序列化时,将详细地探讨这个函数。
注意这个类显式地定义了一个默认的构造函数。这对于序列化操作来说也是必要的,因为从一个文件读取数据时,框架将使用这个默认的构造函数组合一个对象,然后利用来自这个文件的数据填充无参数构造函数生成的组合对象,以设置该对象数据成员的值。