Serialization: Making a Serializable 类

需要五个主要步骤使类是可序列化的。它们在以下各节下面列出并解释:

  1. 派生您的类从 CObject (或从 CObject派生的某些类)。

  2. 重写序列化成员函数。

  3. 在类声明的使用 DECLARE_SERIAL 宏 。

  4. 定义没有参数的构造函数。

  5. 您的类的使用实现文件中的 IMPLEMENT_SERIAL 宏 。

如果通过 CArchive的 >> 和 << 运算符直接调用 Serialize ,而不是前三个步骤对于序列化是必需的。

派生您的类从 CObject

基本序列化协议和函数。 CObject 类中定义。通过派生您的类从 CObject (或从 CObject派生的类),如类中所示 CPerson的以下声明中,您将 CObject的序列化协议和功能的访问。

重写序列化成员函数

Serialize 成员函数,在 CObject 类中定义,对实际序列化所需的数据来获取对象的当前状态。Serialize 函数具有它使用读取和写入对象数据的 CArchive 参数。CArchive 对象的成员函数, IsStoring,指示是否 Serialize 存储区 (写入数据) 或加载 (读取数据)。使用 IsStoring 的结果用作教程中,您的任何插入到对象的数据与插入运算符 (<<) 的 CArchive 对象或与提取运算符 (>>) 来提取数据。

考虑从派生 CObject 有两个新成员变量的类,类型 CStringWORD。下面的类声明片段显示新成员变量和说明重写的 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 );
};

重写序列化成员函数

  1. 调用您的 Serialize 的基类版本,以确保序列化对象的继承部分。

  2. 插入或提取成员变量特定于您的类。

    插入和提取运算符与存档类读取和写入数据。下面的示例演示如何实现声明的 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::ReadCArchive::Write 成员函数读取和写入大量非类型化数据。

使用 DECLARE_SERIAL 宏

DECLARE_SERIAL 宏在支持序列化类的声明需要,如下所示:

class CPerson : public CObject
{
public:
    DECLARE_SERIAL( CPerson )

定义无参数的构造函数

MFC 需要默认构造函数,则重新创建您的对象时,它们被反序列化 (从磁盘加载)。反序列化进程无需的值将填入所有成员变量重新创建对象。

此构造函数可以声明为公共,从而保护或保密。如果要使其成为受保护或私有,有助于确保,它将由序列化功能只使用。构造函数在允许如有必要,删除的状态必须置于对象。

说明说明

如果忘记定义构造函数不在使用 DECLARE_SERIALIMPLEMENT_SERIAL 宏的类的参数,则会在使用 IMPLEMENT_SERIAL 宏的行的 “没有默认构造函数可用”编译器警告。

使用实现文件中的 IMPLEMENT_SERIAL 宏

,当从 CObject时,可序列化派生类 IMPLEMENT_SERIAL 宏用于定义所需的各种功能。在实现文件 (.CPP) 使用此宏对于您的类。对宏的最后两个参数是类的名称及其直接基类的名称。

此宏的第三个参数是模式数字。模式数字实质上是类的对象的版本号。对模式数字使用整数值大于或等于 0。(不要将此模式数字混淆数据库术语。)

,在读取对象到内存中时, MFC 序列化代码检查架构数字。如果对象的架构数字在磁盘上不匹配类的模式数字内存中,库将引发 CArchiveException,以防止程序读取对象的不正确版本。

如果您希望 Serialize 成员函数可以读取多个版本也就是说,文件写入由应用程序的不同版本 —可以使用该值 VERSIONABLE_SCHEMA 作为参数传递给 IMPLEMENT_SERIAL 宏。有关用法信息和示例,请参见类 CArchiveGetObjectSchema 成员函数。

下面的示例演示如何对该类使用 IMPLEMENT_SERIAL , CPerson,从 CObject派生:

IMPLEMENT_SERIAL( CPerson, CObject, 1 )

一旦具有可序列化类,您可以序列化类的对象,如这篇文章 序列化:序列化对象所述。

请参见

概念

在MFC的序列化