Serialization:Making a serializable Class

本文介绍如何通过五个步骤使C++类支持串行化,包括派生于CObject类、重写Serialize函数、使用DECLARE_SERIAL宏等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

串行化:定制一个可串行化的类

要使一个类可以被串行化,需要以下5个步骤:

1.将你的类从CObjcet类派生(或是从CObjcet类的子类派生)。
2.重写成员函数Serialize。
3.在类的声明中添加DECLARE_SERIAL宏。
4.定义一个没有参数的构造函数。
5.在类的实现文件中添加IMPLEMENT_SERIAL宏。

如果你不使用CArchive类的>>和<<运算符,而是直接调用类的Serialize函数,最后3个步骤就不需要了。


使你的类从CObject类派生


串行化的基本协议和功能都在CObjcet类中定义了。通过将你的子类从CObject类(或是COjcet类的子类)派生,如下面CPerson类的声明所显示的一样,你就可以使用Object类的串行化的协议和功能了。

重写Serialize成员函数


Serialize成员函数,定义在CObject类中,负责对用来获取对象当前状态的必要数据进行串行化。Serialize函数带有一个CArchive参数,用来读取和写入对象的数据。CArchive的对象的成员函数IsStoring指示了Serialize函数是存储(写入数据)还是读取(读取数据)。把IsStoring的返回值作为向导,你可以用<<运算符将你的数据插入到CArchive的对象中,或用>>运算符将数据从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.加入或提取你的类特有的成员变量。
插入(“<<”)和提取(“>>”)运算符和archive类相互配合读取和写入数据。
下面的例子展示了如何为上面声明的类实现Serialize函数:

void CPerson::Serialize( CArchive& archive )
{
    // call base class function first     //   首先调用基类的Serialize函数
    // base class is CObject in this case   //   这个例子中基类是CObject
    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
{
    DECLARE_SERIAL( CPerson )
    // rest of declaration follows...
};


定义一个不带参数的构造函数


当你要解串行化你的对象(从磁盘上读取)时,MFC在重新构造你的对象的时候需要一个默认的构造函数。解串行化的过程会给所有成员变量赋值,从而重新构造对象。

这个构造函数可以被声明为公有(public)、保护(protected)、私有(private)类型。如果你将它设为保护或私有类型,你得保证它只能被用来串行化的函数使用。这个构造函数必须使对象在必要的时候允许被安全删除。

注意:在包含DECLARE_SERIAL和IMPLEMENT_SERIAL宏的类中,如果你忘了定义不带参数的构造函数,你会在IMPLEMENT_SERIAL宏处看到“no default constructor available”的编译警告。


在实现文件中使用IMPLEMENT_SERIAL宏


当你从CObject继承一个可串行化的类的时候,IMPLEMENT_SERIAL宏被用来定义各种需要的函数。你应该在你的实现文件(.CPP文件)中使用这个宏。这个宏的第一和第二个参数是你的类的名称和基类(最近的基类)的名称。

宏的第三个参数是个计划号码(schema number).这计划号码本质上是一个类的对象的版本号。计划号码是一个大于或等于0的整数。(不要把这个计划号码和数据库的专用术语混淆起来)

MFC串行化代码会在将对象数据读入内存的时候核对这个版本号。如果从磁盘上读入的对象的版本号和内存里类的版本号不一样,MFC库会产生一个CArchiveException来阻止你的程序读取版本不正确的对象。

如果你希望你的Serialize函数能够读取含有多个版本的对象的文件——也就是由不同版本的应用程序写成的文件——你可以将VERSIONABLE_SCHEMA这个值作为IMPLEMENT_SERIAL宏的参数。要获取使用方法和例子,请查看CArchive的成员函数GetObjectSchema。

下面的例子展示了如何为CPerson类(从CObject派生的类)添加IMPLEMENT_SERIAL宏:
IMPLEMENT_SERIAL( CPerson, CObject, 1 )

一旦你有了一个可串行化的类,你就可以对这个类的对象进行串行化了,就像“Serialization:Serializing an Object”这篇文章中讨论的一样。
<think>好的,我现在需要解决用户的问题:他们在IntelliJ IDEA的检查设置中找不到“Serializable class without 'serialVersionUID’”选项。用户可能已经按照之前的教程操作,但发现该选项不存在,导致无法自动生成serialVersionUID。 首先,我要确认用户的问题可能出在哪里。可能的原因有几个:IDEA版本不同导致选项位置变化,或者相关检查被禁用,或者用户的项目配置有问题。我需要逐一排查这些可能性。 接下来,我应该回想不同IDEA版本的设置是否有差异。比如,较新版本的IDEA可能调整了检查项的分类或名称。用户可能使用的是旧版本,或者某个特定版本中该选项被移动到了其他位置。这时候需要建议用户检查是否在正确的路径下,或者尝试搜索关键字。 另外,用户可能没有正确启用检查。在IDEA中,有些检查默认是关闭的,需要手动开启。用户可能没有勾选对应的检查项,或者误将其禁用。需要引导用户再次确认是否在Editor → Inspections下的Java → Serialization issues中找到该选项,并确保勾选框被选中。 还有一种可能是用户的项目结构或模块设置导致该检查不可见。例如,如果项目没有正确配置为Java项目,或者模块的SDK设置有问题,某些检查可能不会显示。这时候需要建议用户检查项目配置,确保使用的是JDK,并且项目类型正确。 此外,用户可能输入了错误的搜索关键字,或者检查项的名称有变化。比如,某些版本的IDEA可能将检查项命名为“Serializable class without 'serialVersionUID' field”或者其他类似的名称。建议用户使用搜索框,输入“serialVersionUID”或“serializable”来查找相关检查。 如果以上方法都不奏效,可能需要考虑IDEA的插件或设置文件损坏,导致检查项丢失。这时候可以建议用户尝试重置IDEA设置,或者重新安装软件。另外,检查是否有插件冲突,禁用第三方插件后再次尝试。 最后,需要提供替代方案,比如手动生成serialVersionUID的方法,或者使用其他工具如Lombok插件。确保用户即使无法自动生成,也能通过其他方式解决问题。同时,提醒用户注意serialVersionUID的重要性,以及在类结构变化时手动更新的必要性。 总结来说,我需要分步骤引导用户确认检查项的位置,检查IDEA版本和设置,排查项目配置,并提供替代方法,确保用户能够顺利生成所需的serialVersionUID。</think>--- ### 问题分析 如果 **`Serialization issues`** 中找不到 **`Serializable class without 'serialVersionUID'`** 检查项,可能是以下原因导致: 1. **IDEA 版本差异**:不同版本的 IntelliJ IDEA 检查项名称或位置可能略有调整 2. **检查项被禁用**:该检查可能被手动关闭或归类到其他条目下 3. **项目配置问题**:项目未正确识别 Java 环境或序列化相关依赖 --- ### 解决方案 #### 方法 1:通过名称搜索检查项 1. 打开设置:`File → Settings` (Windows/Linux) 或 `IntelliJ IDEA → Settings` (macOS) 2. 进入检查配置页:`Editor → Inspections` 3. **直接搜索关键词**: - 在搜索框输入 `serialVersionUID` 或 `serializable` - 确保勾选搜索结果中的以下条目: ```plaintext [√] Serializable class without 'serialVersionUID' (位于 Java → Serialization issues 分类下) ``` ![IDEA 检查项搜索示意图](https://example.com/placeholder-image-link) --- #### 方法 2:手动定位检查项路径 1. 展开检查树形目录: ```plaintext Java → Serialization issues → Serializable class without 'serialVersionUID' ``` 2. 如果未找到,尝试展开相邻分类: ```plaintext Java → Code style issues → Serializable class without 'serialVersionUID' ``` --- #### 方法 3:验证 IDEA 配置 1. **检查 IDEA 版本**: - 最低要求版本:**IntelliJ IDEA 2018.3+** - 查看版本:`Help → About` - 旧版本建议升级([官网下载](https://www.jetbrains.com/idea/download/)) 2. **重置检查配置**: - 在 `Inspections` 页面点击齿轮图标 → `Restore Defaults` --- #### 方法 4:手动生成 UID(无需检查项) 如果检查项确实缺失,可通过以下方式生成: 1. 在类声明行(`implements Serializable` 处)按 `Alt + Enter` 2. 选择: ```plaintext Add 'serialVersionUID' field → Generate random long ``` ![手动生成操作示意图](https://example.com/placeholder-image-link) --- ### 附加说明 | 现象 | 解决方案 | |--------------------|-----------------------------| | 检查项灰显无法勾选 | 确认项目已关联 JDK(非 JRE) | | 搜索无结果 | 检查是否误开“精简模式”(Power Save Mode) | | 生成按钮不可用 | 确保类已正确定义为 `implements Serializable` | --- ### 技术原理 IDEA 通过 `Serializable` 接口的字节码识别,结合类结构哈希值计算 `serialVersionUID`。若检查项失效,可能是: - `.idea/inspectionProfiles` 配置文件损坏 - 项目模块未启用 Java 语言支持(检查 `File → Project Structure → Modules`) 建议通过 **`File → Repair IDE`** 尝试修复配置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值