Serialization: Making a Serializable 类
需要五个主要步骤使类是可序列化的。它们在以下各节下面列出并解释:
派生您的类从 CObject (或从 CObject派生的某些类)。
重写序列化成员函数。
在类声明的使用 DECLARE_SERIAL 宏 。
定义没有参数的构造函数。
您的类的使用实现文件中的 IMPLEMENT_SERIAL 宏 。
如果通过 CArchive的 >> 和 << 运算符直接调用 Serialize ,而不是前三个步骤对于序列化是必需的。
派生您的类从 CObject
基本序列化协议和函数。 CObject 类中定义。通过派生您的类从 CObject (或从 CObject派生的类),如类中所示 CPerson的以下声明中,您将 CObject的序列化协议和功能的访问。
重写序列化成员函数
Serialize 成员函数,在 CObject 类中定义,对实际序列化所需的数据来获取对象的当前状态。Serialize 函数具有它使用读取和写入对象数据的 CArchive 参数。CArchive 对象的成员函数, IsStoring,指示是否 Serialize 存储区 (写入数据) 或加载 (读取数据)。使用 IsStoring 的结果用作教程中,您的任何插入到对象的数据与插入运算符 (<<) 的 CArchive 对象或与提取运算符 (>>) 来提取数据。
考虑从派生 CObject 有两个新成员变量的类,类型 CString 和 WORD。下面的类声明片段显示新成员变量和说明重写的 Serialize 成员函数:
class CPerson : public CObject
{
public:
DECLARE_SERIAL( CPerson )
// empty constructor is necessary
CPerson();
virtual ~CPerson();
CString m_name;
WORD m_number;
void Serialize( CArchive& archive );
};
重写序列化成员函数
调用您的 Serialize 的基类版本,以确保序列化对象的继承部分。
插入或提取成员变量特定于您的类。
插入和提取运算符与存档类读取和写入数据。下面的示例演示如何实现声明的 CPerson 类的 Serialize 上面:
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; }
还可以使用 CArchive::Read 和 CArchive::Write 成员函数读取和写入大量非类型化数据。
使用 DECLARE_SERIAL 宏
DECLARE_SERIAL 宏在支持序列化类的声明需要,如下所示:
class CPerson : public CObject
{
public:
DECLARE_SERIAL( CPerson )
定义无参数的构造函数
MFC 需要默认构造函数,则重新创建您的对象时,它们被反序列化 (从磁盘加载)。反序列化进程无需的值将填入所有成员变量重新创建对象。
此构造函数可以声明为公共,从而保护或保密。如果要使其成为受保护或私有,有助于确保,它将由序列化功能只使用。构造函数在允许如有必要,删除的状态必须置于对象。
说明 |
---|
如果忘记定义构造函数不在使用 DECLARE_SERIAL 和 IMPLEMENT_SERIAL 宏的类的参数,则会在使用 IMPLEMENT_SERIAL 宏的行的 “没有默认构造函数可用”编译器警告。 |
使用实现文件中的 IMPLEMENT_SERIAL 宏
,当从 CObject时,可序列化派生类 IMPLEMENT_SERIAL 宏用于定义所需的各种功能。在实现文件 (.CPP) 使用此宏对于您的类。对宏的最后两个参数是类的名称及其直接基类的名称。
此宏的第三个参数是模式数字。模式数字实质上是类的对象的版本号。对模式数字使用整数值大于或等于 0。(不要将此模式数字混淆数据库术语。)
,在读取对象到内存中时, MFC 序列化代码检查架构数字。如果对象的架构数字在磁盘上不匹配类的模式数字内存中,库将引发 CArchiveException,以防止程序读取对象的不正确版本。
如果您希望 Serialize 成员函数可以读取多个版本也就是说,文件写入由应用程序的不同版本 —可以使用该值 VERSIONABLE_SCHEMA 作为参数传递给 IMPLEMENT_SERIAL 宏。有关用法信息和示例,请参见类 CArchive的 GetObjectSchema 成员函数。
下面的示例演示如何对该类使用 IMPLEMENT_SERIAL , CPerson,从 CObject派生:
IMPLEMENT_SERIAL( CPerson, CObject, 1 )
一旦具有可序列化类,您可以序列化类的对象,如这篇文章 序列化:序列化对象所述。