-
1.
为什么要序列化
回答:
我们在开发基于单文档的
p>
SDI
程序的时候,
对于文档
/
视图机制中的数据交
换有了一定的了解。大体的流
程是。文档类负责处理一些数据,然后通过调用
UpdateAllViews
函数通知视图类。
然后视图类通过获得指向文档类的指针,
来
获取文档类的实时更新的数据,
并且在相应的视图
类里面调用相关函数完成一定
的功能。
但是,
我们始终没有触及到文档类与外部数据的机制,
比如菜
单里面的新建,
打开,保存等选项,这些选项就是用来与外部数据打交道的。那么,这样
文档类
与外部数据到底该如何实现交换呢,
以及当前程序里面的
数据是否具有可持续功
能,这就要用到序列化的思想了。
p>
为了下面的讲解方便,我们仍然采用上一讲的分割视图的范例程序
Ex_MultiView_
交互
2
为该工程创建一个可序列化的类
⑴点击菜单中
Insert
–
>New
Class
,并且命名以及基类选择如下(必须选择
基类为
CO
bject
类)
⑵为新建的类添加成员变量以及支持序列化的相关功能。
p>
CStudent
类的头文件
Studen
t.h
class CStudent : public CObject
{
public:
CStudent(CString
num,CString
name,CString
magor,CString
home);
CStudent();
CStudent(CStudent &stu);
void
GetData(CString
&num,CString
&magor,CString
&home);
CStudent&
operator=(CStudent stu);
virtual ~CStudent();
DECLARE_SERIAL(CStudent);
virtual void Serialize(CArchive &ar);
private:
CString
m_strName;
CString m_strNum;
CString m_strMagor;
CString m_strHome;
};
CStudent
类的源文件
IMPLEMENT_SERIAL(CStudent,CObject,1)
CStudent::CStudent()
{
}
CStudent::CStudent(CString
num,CString
magor,CString
home)
{
m_strName
= name;
m_strNum
= num;
m_strMagor = magor;
m_strHome
=
home;
}
CStudent::CStudent(CStudent &stu)
{
m_strName
= stu.m_strName;
m_strNum
= stu.m_strNum;
m_strMagor = stu.m_strMagor;
&name,CString
name,CString
m_strHome
= stu.m_strHome;
}
void
CStudent::GetData(CString
&num,CString
&name,CString
&magor,CString &home)
{
name
=
m_strName;
num
= m_strNum;
magor = m_strMagor;
home
=
m_strHome;
}
CStudent& CStudent::operator=(CStudent
stu)
{
m_strName
= stu.m_strName;
m_strNum
= stu.m_strNum;
m_strMagor = stu.m_strMagor;
m_strHome
= stu.m_strHome;
return *this;
}
void CStudent::Serialize(CArchive& ar)
{
if (ing())
{
<
/p>
<
br>宏调用。 <
br>IMPLEMENT_SERIAL
ar<
}
else
{
ar>>m_strNum>>m
_strName>>m_strMagor>>m_strHome;
}
}
CStudent::~CStudent()
{
}
关于这个类中的的若干代码的解释:
解释一:
可序列化的类必须直接或间
接从
CObject
派生。
在类声明中,必须包括
DECLARE_SERIAL
在类的实现文件中必须包括
宏调用。
解释二:
磁盘文件和归档(
Archives
):
在
MFC
库中,磁盘文件是通过
CF
ile
类的对象来表示的。
如果应用
程序不直接利用磁盘
I/O
,
而只依赖
于序列化处理过程,
则可以避免直
接使用
CFile
对象。
在
serialize
函数
(序列化函数)
与
CFile
对象之间,
还有一个归档对象
(
CArchive
类对象)
,
归档对象为
CFile
p>
对象缓存数据,同时还保存一个内部标记,用来标
示归档存档(写盘
)还是载入(读盘)。
每次只能有一个活动的归档与文件相连
。
应用程序框架会很好管理
CFile
对象及
CArchive
对象的创建,为
CFile
对象打开相应的磁盘文件,并且将相应的归档
对象
与文件对象相连。
关系图:
持续文档对象
<
--
> Serialize
<
--
>
CArchive
对象
<
--
>
CFile
对象
<
--
>
磁盘
当用户选择了
File
Open
或
File Save
命令时
,
应用程序框架自动调用
Serialize
< br>函数。
我们可以看到在本程序中,
CStu
dent
类的头文件
Student.h
中有一个虚函数
virtual
void
Serialize(CArchive
&ar);
就是这个函数实现数据与文件的归档
功能
编写
Serialize
函数,实现下列数据的串行化处理
m_st
rNum
,
m_strName
,
p>
m_strMagor
和
m_strHom
e
void CStudent::Serialize(CArchive&
ar)
{
if
(ing())
判断当前归档是被用来存入还是被用来载入的。
{
<
/p>
ar<
}
else
{
ar>>m_strNum>>m
_strName>>m_strMagor>>m_strHome;
}
}
3.
为该工程的文档类添加序列化的
功能
⑴进入文档类的头文件
#include
#include
class
CEx_MultiViewDoc : public CDocument
{
protected: // create from serialization
only
CEx_MultiViewDoc();
DECLARE_DYNCREATE(CEx_MultiViewDoc)
// Attributes
public:
//CString Data[4];
int
nIndex;
BOOL bAdd;
CObArray m_StudentArray;
//
省略部分代码
}
;
语句
#include
表示为文档类
添加
Cstudent
的类声明
语句
CObArray m_StudentArray;
p>
表示为文档类添加一个对象指针数组类
C
obArray
的对象
m_StudentArray
用来保存相关的学生数据
要使用这个类必须添加头文件
Afxcoll.h
⑵进入文档类的实现文件,为序列化函数添加代码如下
void
CEx_MultiViewDoc::Serialize(CArchive& ar)
{
if (ing())
{
// TODO: add storing code here
m_ize(ar);
}
else
{
// TODO: add
loading code here
m_ize(ar);
}
}
这样
,文档类里面就有了一个可序列化的指针数组
m_StudentArray
,同学们
一定明白了,
这个指针数组里面存放的就
是相关的学生的数据,
但是同学们一定
会问,
< br>这个可序列化的指针数组对象
m_StudentArray
和我们刚才建立的那个
可序列化的
Cstudent
类有什么关系呢?通过以下的几个步骤我们就会明白:
-
-
-
-
-
-
-
-
-
上一篇:实验2 类的定义与应用
下一篇:软件开发工具与环境模拟题二及答案