第1节 CFile→CArchive→CDocument的进化过程
传统的数据存储结构,一般是将所有要存储的各种数据定义到一个结构体中,再以结构体对象为单元通过CFile对象循环读/写数据。CArchive类没有基类,它对CFile类简单地再封装,其中大量重载了“operator<<”和“operator>>”函数,使各种类型数据的文件存储更加方便。CArchive类的输入/输出功能,仿制了标准C++的fstream类的输入/输出符号,然而被CDocument类引用后巧妙地搭建起序列化高级存储架构。
创建一个工程名为“f”的对话框程序,用于演示从CFile到CDocument存储架构的进化过程。
1)在主对话框中添加一些控件,如图13-2所示。

图13-2 编辑主对话框资源
2)修改控件属性,见表13-1。
表13-1 主对话框的控件属性

3)通过类向导为列表控件建立控件型关联变量,如图13-3所示。

图13-3 添加控件型关联变量
4)修改对话框初始化函数代码。

5)建立“添加”按钮的消息映射函数并修改代码。

6)建立“保存”和“加载”按钮的消息映射函数并修改代码。


7)编译并运行,测试代码。
在对话框列表内随意添加一些数据,然后单击“保存”按钮,重启进程后再单击“加载”按钮。这是最原始的文件保存方式,在前面章节已有介绍。
重新创建一个工程名为“a”的对话框程序,用于演示使用CArchive类存储文件的方式。
8)在主对话框内添加一些控件,种类和ID与“f”工程完全一致,如图13-4所示。

图13-4 编辑主对话框资源
9)通过类向导为列表控件添加关联变量m_list,再修改对话框初始化函数代码。

10)分别建立“添加”“保存”和“加载”按钮的消息映射函数并修改代码。


11)编译并运行,测试代码。
在对话框列表内随意添加一些数据,然后单击“保存”按钮,重启进程后再单击“加载”按钮。(https://www.daowen.com)
使用归档类(CArchive)进行文件存储的特点如下。
①不需要使用固定大小的结构体对象作为存储单元循环进行操作。
②数据存储紧凑无冗余,生成的文件的大小是所有输出变量大小和字符串长度的和。
③归档文件使用输入/输出符号传递存储对象,使编写程序更加灵活方便,开发效率更高。
重新创建一个工程名为“d”的对话框程序,用于演示使用CDocument类的串行化存储架构。
12)在主对话框内添加一些控件,与“f”工程完全一致,为列表控件添加关联变量m_list。

13)在类视图中添加一个CDocument派生类,如图13-5所示。

图13-5 创建稳当类的派生类
14)修改刚添加的CDoc类头文件,将构造函数的权限由保护改为公有。

15)在主对话框类头文件中,添加CDoc类型成员变量。

16)分别建立“添加”“保存”和“加载”按钮的消息映射函数并修改代码。

17)在类视图中为主对话框类添加序列化函数,如图13-6所示。

图13-6 添加普通成员函数
18)修改序列化函数代码。

19)修改CDoc类的序列化函数代码。

20)编译并运行,测试代码。
在对话框列表内随意添加一些数据,然后单击“保存”按钮,重启进程后再单击“加载”按钮。
CDocument类实现序列化存储的核心是Serialize函数,它既负责用户数据保存也负责数据加载。Serialize函数通过参数(CArchive::IsStoring)判断任务性质,如果是正在执行保存任务,则调用输出符号将用户输入的数据保存到文件中,否则调用输入符号将文件中存储的数据读取到应用程序中。
在MSDN索引中输入“Serialize”查看,Serialize是MFC顶层基类CObject中的虚函数,因此,几乎所有MFC派生类都支持该虚函数,如图13-7所示。

图13-7 查看MSDN函数说明