Persistence(永久保存)机制

本文介绍MFC框架下的序列化机制,重点讲解如何通过自定义序列化函数实现对象的持久化存储,并探讨版本控制和对象动态创建等问题。

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

面向对象有一个术语:Persistence,意思就是把对象永久保存下来。Power一关,啥都没有,对象如何能够永久保存呢?当然是写到文件中去了。把数据写到文件,很简单。在Document/CView结构中,数据都放在一份document里,我们只要把其中的成员变量依次写进文件即可。成员变量很肯能是一个对象,我们首先应该记载其类名称,然后才是对象中的数据。读取文档就有点麻烦了,当程序从文档中读到一个类名称时,它如何实例化(instance)一个对象?呵呵,这不就是动态创建的技术吗,我们在前面文章中已经解决掉了。 MFC有一套Serialize机制,目的在于把文件名的选择、文件的开关、缓冲区的建立、数据的读写、提取运算符>>和插入运算符<<的重载、对象的动态创建等都包装起来。上述Serialize的各部分工作,除了数据的读写和对象的动态创建外,其余都是枝节。动态创建的技术已经解决,让我们集中火力,分析数据的读写操作。

      假设我有一份文件,用于记录一张图形,图形只有3种基本元素:线条(Stroke)、圆形、矩形。我打算用类来组织这份文件。

 

其中COblist和CDwordArray是MFC提供的类,前者是一个链表,可放置任何从CObject派生下来的对象,后者是一个数组,每一个元素都是double word。另外3个类:CStroke、CRectangle、CCircle是我从CObject中派生下来的类。

      假设有一份文件,文件中的数据为一个链表CObList m_graphList;其中链表中包含了100条线条、50个圆形、80个矩形、难道我们要记录230个类名称不成?当然不必,我们可以在每次记录对象内容的时候,先写入一个代码,表示此对象的类是否曾在文件中记录过了。如果是新类,乖乖的记录其类名称;如果是旧类,则以代码表示,这样可以节省文件大小以及程序用于解析的时间。啊,不要看到文件大小就想到硬盘很便宜,桌上的一切都将被带到网上,你得想想网络带宽这回事。

      还有一个问题。文件的版本如何控制,旧版程序读取新版文件,新版程序读取旧版文件,都可能出问题,为了防弊,最好把版本号记录上去,最好是每个类都有自己的版本号码。

      我希望有一个专门负责Serialization的函数,就叫做Serialize好了,假设现在我的Document类名称为CScribDoc,我希望有这么便利的程序方法:

 

每一个可写到文件或可从文件读取的类,都应该有自己的Serilize函数,负责把自己的数据读写文件操作。此类并且应该改写<<运算符和>>运算符。把数据导流到archive中,archive是什么?是一个与文件息息相关的缓冲区,暂时你可以想象他就是文件的化身。当CObList列表写入文件时,以此调用每个类的Serialize函数。

DECLARE_SERIAL/IMPLEMENT_SERIAL宏

      要将<<和>>两个运算符重载,还要让Serialize函数神不知鬼不觉的放入类声明之中,最好的做法仍然是宏。类之所以能够进行文件读写操作,前提是拥有动态创建的能力,所以,MFC设计了两个宏DECLARE_SERIAL和IMPLEMENT_SERIAL:

 

为了在每一个对象被处理(读或写)之前,能够处理琐屑的工作,诸如是否是第一次出现、记录版本号码、记录文件名等工作,CRuntimeClass需要2个函数Load和Store,这两个函数需要在CRuntimeClass结构体中增加。

      为了让整个Serialization机制运行起来,我们必须做这样的类声明:

 

然后分头设计CStroke、CRectangle、CCircle的Serialize函数即可。

资源下载链接为: https://pan.quark.cn/s/9648a1f24758 MySQL SSH隧道连接是一种安全的远程访问MySQL数据库的方式,尤其适用于无法直接远程访问MySQL服务器的场景。通过SSH协议建立安全通道,将本地网络连接转发至远程服务器,从而实现本地对远程数据库的访问,就如同访问本地MySQL服务一样。 如果之前为root用户分配了远程访问权限,出于安全考虑,可以按照以下步骤收回权限: 登录MySQL服务器:mysql -uroot -p。 查看当前用户的远程访问权限:select user, host from mysql.user;。 删除不必要的远程访问权限(例如限制root用户从所有主机访问):delete from mysql.user where user='root' and host='%';。 刷新权限以应用更改:flush privileges;。 再次查询,确认root用户已无法从任何远程主机登录。 接下来,需要建立SSH隧道。通常使用SSH客户端(如OpenSSH)连接到远程服务器,并通过RSA密钥对进行身份验证,这是一种更安全的认证方式。如果本地尚未生成RSA密钥对,需要先生成密钥对,并将公钥(id_rsa.pub)添加到远程服务器的~/.ssh/authorized_keys文件中。建立SSH隧道的命令如下(需替换为实际的IP地址和端口号): 参数含义如下: -N:仅建立隧道,不执行远程命令。 -C:启用压缩(可选)。 -P:使用非特权端口。 -f:建立隧道后在后台运行。 [email protected]:SSH用户名和目标服务器IP。 -L 3388:127.0.0.1:3306:将本地端口3388映射到远程服务器的MySQL端口3306。 之后,可以使用本地MySQL客户端工具(如MySQL Workben
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值