MFC + 自定义类的序列化与反序列化

使类可序列化需要五个主要步骤。

  1. 从 CObject 派生类(或从 CObject 派生的某个类中派生)。
  2. 重写 Serialize 成员函数
  3. 使用 DECLARE_SERIAL 宏(在类声明中)。
  4. 定义不带参数的构造函数
  5. 为类在实现文件中使用 IMPLEMENT_SERIAL 宏

如果直接调用 Serialize 而不是通过 CArchive 的“>>”和“<<”运算符调用,则序列化不需要最后三个步骤。

从 CObject 派生类

在 CObject 类中定义了基本的序列化协议和功能。正如在 CPerson 类的下列声明中所示,通过从 CObject 中(或从 CObject 的派生类中)派生类,可获得对 CObject 的序列化协议及功能的访问权限。

重写 Serialize 成员函数

在 CObject 类中定义的 Serialize 成员函数实际上负责对捕获对象的当前状态所必需的数据进行序列化。Serialize 函数具有 CArchive 参数,该函数使用其来读写对象数据。CArchive 对象具有成员函数 IsStoring,该成员函数指示 Serialize 正在存储(即正在写入数据)还是正在加载(即正在读取数据)。用 IsStoring 的结果作为参考,使用输出运算符 (<<) 将对象数据插入到 CArchive 对象中或使用输入运算符 (>>) 提取数据。

假定一个类是从 CObject 派生的并具有两个新成员变量,分别为 CString 和 WORD 类型。下列类声明段显示了新成员变量和重写的 Serialize 成员函数的声明:

class CPerson : public CObject
{
public:
    DECLARE_SERIAL( CPerson )
    // empty constructor is necessary
    CPerson(){};

    CString m_name;
    WORD   m_number;

    void Serialize( CArchive& archive );
    
    // rest of class declaration
};

重写 Serialize 成员函数

  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、CArchive::ReadString、CArchive::WriteString、CArchive::ReadObject、CArchive::WriteObject 成员函数来读写大量未键入的数据。

使用 DECLARE_SERIAL 宏

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

class CPerson : public CObject
{
    DECLARE_SERIAL( CPerson )
    // rest of declaration follows...
};

定义不带参数的构造函数

反序列化对象(从磁盘上加载)后,MFC 重新创建这些对象时,需要一个默认的构造函数。反序列化进程将用重新创建对象所需的值填充所有成员变量。

可将该构造函数声明为公共的、受保护的或私有的。如果使该构造函数成为受保护的或私有的,请确保它将仅由序列化函数使用。该构造函数必须使对象处于这样一种状态:必要时,可允许将其安全删除。

注意   如果忘记在使用  DECLARE_SERIAL 及  IMPLEMENT_SERIAL 宏的类中定义不带参数的构造函数,将在使用 IMPLEMENT_SERIAL 宏的行上得到“没有可用的默认构造函数”编译器警告。

在实现文件中使用 IMPLEMENT_SERIAL 宏

IMPLEMENT_SERIAL 宏用于定义从 CObject 中派生可序列化类时所需的各种函数。在类的实现文件 (.CPP) 中使用这个宏。该宏的前两个参数是类名和直接基类的名称。

该宏的第三个参数是架构编号。架构编号实质上是类对象的版本号。架构编号使用大于或等于零的整数。(请不要将该架构编号与数据库术语混淆。)

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

如果要使 Serialize 成员函数能够读取多个版本(即,读取用应用程序的不同版本写入的文件),可将 VERSIONABLE_SCHEMA 值作为IMPLEMENT_SERIAL 宏的参数。

以下示例显示了如何将 IMPLEMENT_SERIAL 用于从 CObject 派生的 CPerson 类。

IMPLEMENT_SERIAL( CPerson, CObject, 1 )

正如序列化:序列化对象文章中所讨论的,一旦具有可序列化的类,就可以序列化类的对象。

使用范例:

CFile m_File;

m_File.Open(XXX);//注意CFile对象的状态要与CArchive对象的状态保持一致   并且两者应该一一对应

CPerson m_Person;

CArchive m_ar(&m_File,CArchive::Mode::load);        //写模式为CArchive::Mode::store

m_Person.serialize(m_ar);

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MFC(Microsoft Foundation Classes)是微软提供的一套用于开发Windows桌面应用程序的C++库。在MFC中,序列化(Serialization)是指将对象的状态转换为可以存储或传输的格式,而反序列化(Deserialization)则是将存储或传输的数据恢复为对象的状态。 MFC提供了一些和宏来支持序列化反序列化操作,主要涉及以下几个: 1. CObject:所有支持序列化MFC都继承自CObject。它提供了一些虚拟函数,如Serialize用于实现对象的序列化反序列化操作。 2. CArchive:用于创建和操作存储或传输数据的存档文件。CArchive提供了Serialize函数,用于将对象的状态写入存档文件或从存档文件中读取对象的状态。 3. CFile:用于对文件进行读写操作。它提供了Open、Read、Write等函数来操作文件。CArchive可以使用CFile来读写数据。 下面是一个简单的示例代码,演示了如何在MFC中进行序列化反序列化操作: ```cpp // 假设有一个自定义MyData,需要支持序列化反序列化 class MyData : public CObject { public: int m_value; // 实现Serialize函数来进行对象的序列化反序列化操作 void Serialize(CArchive& ar) { if (ar.IsStoring()) // 写入数据 ar << m_value; else // 读取数据 ar >> m_value; } }; // 序列化操作 void SerializeData() { CFile file(_T("data.dat"), CFile::modeCreate | CFile::modeWrite); CArchive ar(&file, CArchive::store); MyData data; data.m_value = 42; data.Serialize(ar); // 将对象的状态写入存档文件 ar.Close(); file.Close(); } // 反序列化操作 void DeserializeData() { CFile file(_T("data.dat"), CFile::modeRead); CArchive ar(&file, CArchive::load); MyData data; data.Serialize(ar); // 从存档文件中读取对象的状态 ar.Close(); file.Close(); // 使用反序列化后的对象... int value = data.m_value; } ``` 在上述示例中,Serialize函数根据ar对象的状态进行读写操作,将m_value成员变量的值进行序列化反序列化。通过创建CFile和CArchive对象,可以实现对存档文件的读写操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值