若要使类可序列化,需要执行五个主要步骤。 下面列出了它们,并在以下部分中进行了说明:
从 CObject 派生类 (或派生自
CObject
某些类)。在类声明中使用 DECLARE_SERIAL 宏。
如果直接调用 CArchive 而不是通过 >><< 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 重新创建对象时,MFC 需要默认构造函数,因为它们是反序列化的(从磁盘加载的)。 反序列化过程将使用重新创建对象所需的值填充所有成员变量。
此构造函数可以声明为公共、受保护或私有。 如果将其设置为受保护或专用,则有助于确保它只供序列化函数使用。 构造函数必须使对象处于允许在必要时删除的状态。
注释
如果忘记在使用DECLARE_SERIAL和IMPLEMENT_SERIAL宏的类中定义没有参数的构造函数,则会在使用IMPLEMENT_SERIAL宏的行上收到“没有可用的默认构造函数”编译器警告。
在实现文件中使用IMPLEMENT_SERIAL宏
IMPLEMENT_SERIAL宏用于定义从中 CObject
派生可序列化类时所需的各种函数。 在实现文件中使用此宏(。你的课堂的 CPP。 宏的前两个参数是类的名称及其直接基类的名称。
此宏的第三个参数是架构编号。 架构编号实质上是类对象的版本号。 对架构编号使用大于或等于 0 的整数。 (不要将此架构编号与数据库术语混淆。
MFC 序列化代码在将对象读入内存时检查架构编号。 如果磁盘上对象的架构编号与内存中类的架构编号不匹配,库将引发一个 CArchiveException
,从而阻止程序读取对象的不正确版本。
如果希望 Serialize
成员函数能够读取多个版本(即使用不同版本的应用程序编写的文件),则可以使用值 VERSIONABLE_SCHEMA 作为IMPLEMENT_SERIAL宏的参数。 有关用法信息和示例,请参阅 GetObjectSchema
类 CArchive
的成员函数。
以下示例演示如何对派生自CObject
的类CPerson
使用 IMPLEMENT_SERIAL:
IMPLEMENT_SERIAL(CPerson, CObject, 1)
拥有可序列化类后,可以序列化类的对象,如序列化 :序列化对象一文中所述。