使用MFC::CArchive

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

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

现在动手

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

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

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

 
 
  1. class CPerson : public CObject
  2. {
  3. DECLARE_SERIAL(CPerson)
  4. private:
  5. CString _name;
  6. int _age;
  7. bool _gender;
  8. CString _words;
  9. public:
  10. CPerson();
  11. CPerson(CString name, int age, bool gender = true);
  12. CString getName();
  13. CString getWords();
  14. void setWords(CString words);
  15. int getAge();
  16. bool isMale();
  17. void say();
  18. void say(CString msg);
  19. virtual void Serialize(CArchive& ar);
  20. };

CPerson类的实现如下:

 
 
  1. #include "stdafx.h"
  2. #include "mfc-person.h"
  3. IMPLEMENT_SERIAL(CPerson, CObject, 1)
  4. CPerson::CPerson()
  5. {
  6. _name = _T("无名氏");
  7. _age = 0;
  8. _gender = true;
  9. }
  10. CPerson::CPerson(CString name, int age, bool gender)
  11. {
  12. _name = name;
  13. _age = age;
  14. _gender = gender;
  15. }
  16. CString CPerson::getName()
  17. {
  18. return _name;
  19. }
  20. CString CPerson::getWords()
  21. {
  22. return _words;
  23. }
  24. void CPerson::setWords(CString words)
  25. {
  26. _words = words;
  27. }
  28. int CPerson::getAge()
  29. {
  30. return _age;
  31. }
  32. bool CPerson::isMale()
  33. {
  34. return _gender;
  35. }
  36. void CPerson::say()
  37. {
  38. say(_words);
  39. }
  40. void CPerson::say(CString msg)
  41. {
  42. _tprintf(_T("%s: %s\r\n"), _name, msg);
  43. }
  44. void CPerson::Serialize(CArchive& ar)
  45. {
  46. if (ar.IsStoring())
  47. {
  48. ar << this->_name<<this->_age<<this->_gender << this->_words;
  49. }
  50. else
  51. {
  52. ar >> this->_name>>this->_age>>this->_gender >> this->_words;
  53. }
  54. }

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

 
 
  1. #include "stdafx.h"
  2. #include "mfc-person.h"
  3. #include "ArchiveTest.h"
  4. int main()
  5. {
  6. setlocale(LC_ALL, "chs");
  7. //创建两个待写入的对象
  8. CPerson tong(_T("佟湘玉"), 28, false);
  9. tong.setWords(_T("额滴神啊..."));
  10. CPerson bai(_T("白展堂"), 27, true);
  11. bai.setWords(_T("葵花点穴手!"));
  12. //准备写入
  13. CFile oFile(_T("persons.archive"),CFile:: modeCreate|CFile::modeWrite);
  14. CArchive oar(&oFile, CArchive::store);
  15. //序列化进去了
  16. oar << &tong << &bai;
  17. //oar.WriteObject(&tong);
  18. //oar.WriteObject(&bai);
  19. oar.Close();
  20. oFile.Close();
  21. //准备读取
  22. CFile iFile(_T("persons.archive"), CFile::modeRead);
  23. CArchive iar(&iFile, CArchive::load);
  24. CPerson *p1, * p2;
  25. //序列化出来了
  26. iar >> p1 >> p2;
  27. //p1 = iar.ReadObject(RUNTIME_CLASS(CPerson));
  28. //p2 = iar.ReadObject(RUNTIME_CLASS(CPerson));
  29. //看看他们是不是活的*_*ii
  30. p1->say();
  31. p2->say();
  32. delete p1;
  33. delete p2;
  34. }

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

图6-19 运行结果

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

(点击查看大图)图6-20 CArchive生成的二进制内容

还有一个问题:为什么我们可以使用"oar << &tong << &bai"和"iar >> p1 >> p2"? 实际上CArchive包含了支持"CObject *"参数的流操作符:

 
 
  1. _AFX_INLINE CArchive& AFXAPI operator<<(CArchive& ar, const CObject* pOb)
  2. {
  3. ar.WriteObject(pOb);
  4. return ar;
  5. }
  6. _AFX_INLINE CArchive& AFXAPI operator>>(CArchive& ar, CObject*& pOb)
  7. {
  8. pOb = ar.ReadObject(NULL);
  9. return ar;
  10. }

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

(点击查看大图)图6-21 CArchive的调用流程

这正是MFC的精妙之处,它让CPerson不知不觉地就具备了的持久化和反持久化的功能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值