您的位置:首页 > 其它

6.3.4 使用MFC::CArchive

2010-01-07 21:25 232 查看
6.3.4 使用MFC::CArchive

准确地说,CArchive也属于二进制变长数据,由于CArchive采用了CObject的RTTI特性,同时存储了对象类的信息,因此它对于CObject对象的持久化和反持久化来说,的确是"很好很强大"。

早在第3章我们结合CObject讨论过CArchive的相关知识,要想用上CArchive的强大功能,我们需要做的仅仅是将自己的类定义成支持自创建的CObject子类,并且覆盖默认的Serialize()函数。

现在动手

以下我们将准备一个示例,使用CArchive实现CPerson对象的持久化和反持久化。

选择【Win32】→【Win32项目】→【控制台程序】命令,创建ArchiveTest。

新建CPerson类,CPerson的定义如下:

class CPerson : public CObject
{
DECLARE_SERIAL(CPerson)
private:
CString _name;
int _age;
bool _gender;
CString _words;
public:
CPerson();
CPerson(CString name, int age, bool gender = true);
CString getName();
CString getWords();
void setWords(CString words);
int getAge();
bool isMale();
void say();
void say(CString msg);
virtual void Serialize(CArchive& ar);
};

CPerson类的实现如下:

#include "stdafx.h"
#include "mfc-person.h"

IMPLEMENT_SERIAL(CPerson, CObject, 1)

CPerson::CPerson()
{
_name = _T("无名氏");
_age = 0;
_gender = true;
}

CPerson::CPerson(CString name, int age, bool gender)
{
_name = name;
_age = age;
_gender = gender;
}

CString CPerson::getName()
{
return _name;
}

CString CPerson::getWords()
{
return _words;
}

void CPerson::setWords(CString words)
{
_words = words;
}

int CPerson::getAge()
{
return _age;
}

bool CPerson::isMale()
{
return _gender;
}

void CPerson::say()
{
say(_words);
}

void CPerson::say(CString msg)
{
_tprintf(_T("%s: %s/r/n"), _name, msg);
}

void CPerson::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
ar << this->_name<<this->_age<<this->_gender << this->_words;
}
else
{
ar >> this->_name>>this->_age>>this->_gender >> this->_words;
}
}

修改主程序,在main()中创建两个CPerson对象,然后将其持久化到文件中,再将其从文件中反持久化出来,调用对象的方法,试试它们还是不是活的:

#include "stdafx.h"
#include "mfc-person.h"
#include "ArchiveTest.h"

int main()
{
setlocale(LC_ALL, "chs");

//创建两个待写入的对象
CPerson tong(_T("佟湘玉"), 28, false);
tong.setWords(_T("额滴神啊..."));

CPerson bai(_T("白展堂"), 27, true);
bai.setWords(_T("葵花点穴手!"));

//准备写入
CFile oFile(_T("persons.archive"),CFile::
modeCreate|CFile::modeWrite);
CArchive oar(&oFile, CArchive::store);

//序列化进去了
oar << &tong << &bai;
//oar.WriteObject(&tong);
//oar.WriteObject(&bai);

oar.Close();
oFile.Close();

//准备读取
CFile iFile(_T("persons.archive"), CFile::modeRead);
CArchive iar(&iFile, CArchive::load);

CPerson *p1, * p2;

//序列化出来了
iar >> p1 >> p2;
//p1 = iar.ReadObject(RUNTIME_CLASS(CPerson));
//p2 = iar.ReadObject(RUNTIME_CLASS(CPerson));

//看看他们是不是活的*_*ii
p1->say();
p2->say();

delete p1;
delete p2;
}

运行结果如图6-19所示,可以看出,作为被序列化的CPerson对象,佟掌柜和老白完完全全活过来了。



图6-19 运行结果
比较好奇的读者可以查看一下其生成的二进制文件,这个persons.archive看起来比较乱,但根据运行结果中佟湘玉和白展堂说的两句话,我们不必担心该存储方式的准确性,CArchive生成的二进制内容如图6-20所示。


(点击查看大图)图6-20 CArchive生成的二进制内容
还有一个问题:为什么我们可以使用"oar << &tong << &bai"和"iar >> p1 >> p2"? 实际上CArchive包含了支持"CObject *"参数的流操作符:

_AFX_INLINE CArchive& AFXAPI operator<<(CArchive& ar, const CObject* pOb)
{
ar.WriteObject(pOb);
return ar;
}

_AFX_INLINE CArchive& AFXAPI operator>>(CArchive& ar, CObject*& pOb)
{
pOb = ar.ReadObject(NULL);
return ar;
}

感兴趣的程序员可以究根求源,打开CArchive的源码,就会发现WriteObject()和ReadObject()会反过来调用CObject的Serialize()函数,调用流程如图6-21所示。



(点击查看大图)图6-21 CArchive的调用流程
这正是MFC的精妙之处,它让CPerson不知不觉地就具备了的持久化和反持久化的功能。

===========================================

以上摘自《把脉VC++》 http://www.china-pub.com/195701 第6.3.4小节的内容 ,转载请注明出处。

如果你想与我交流,请点击如下链接加我为好友:http://student.csdn.net/invite.php?u=113292&c=8913f87cffe7d533
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: