Persistence的实现其实就是Serialize,书中总结要实现Serialize的5个必要条件:
1. 从CObject 衍生下来。如此一来可保有RTTI、Dynamic Creation 等机能。
2. 类别的声明部份必须有DECLARE_SERIAL 宏。此宏需要一个参数:类别名称。
3. 类别的实作部份必须有IMPLEMENT_SERIAL 宏。此宏需要三个参数:一是类别名称,二是父类别名称,三是schema no.。
4. 改写Serialize 虚函数,使它能够适当地把类别的成员变量写入文件中。
5. 为此类别加上一个default 构造式(也就是无参数之构造式)。这个条件常为人所忽略,但它是必要的,因为若一个对象来自文件,MFC 必须先动态生成它,而且在没有任何参数的情况下调用其构造式,然后才从文件中读出对象资料。
说明:
要实现Serialize必须具备RTTI、Dynamic Creation,即运行时类型识别与动态生成技术。
CObject中包含了实现这些功能的接口。
MFC中实现RTTI在类阶层中保存一个CRuntimeClass类型静态变量,在实作代码中初始化,并构造一个静态AFX_CLASSINIT(故能在程序一开始时就完成类别网的构建)在其构造函数中将CRuntimeClass加入CRuntimeClass列表。这些功能均通过DECLARE_DYNAMIC / IMPLEMENT_DYNAMIC这两个宏完成。
为了实现Dynamic Creation则需要有通过CRuntimeClass创建CObject的能力。故CRuntimeClass会保存类型表中创建自身的static函数(回调)并在实作中new出自身(调用无参构造函数)。此功能通过DECLARE_DYNCREATE/IMPLEMENT_DYNCREATE这一对宏完成。
MFC使用CArchive将类写入到文件缓冲区,为了使CArchive类能够读写(>>)自身信息,重载操作符(>>)最终调用CArchive的WriteObject函数,先写CRuntimeClass信息,再调用虚函数Serialize写入类属性,因此需要改写Serialize。以上通过DECLARE_SERIAL / IMPLEMENT_SERIAL这一对宏实现。
总结:
RTTI、Dynamic Creation、Persistence三大机制通过几对宏定义实现,避免了层次较深的子类巨大的虚函数表的负累是聪明的实现。
但所有这些均基于MFC的类阶层,故需牢记MFC的类阶层。