[普通]CArchive解析

作者(passion) 阅读(1039次) 评论(0) 分类( c++)

准确地说,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所示。

blob.png


还有一个问题:为什么我们可以使用"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所示。

blob.png

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

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


« 上一篇:wifi共享上网(至尊版wifi)
« 下一篇:drcom至尊版使用openwrt路由器拨号
在这里写下您精彩的评论
  • 微信

  • QQ

  • 支付宝

返回首页
返回首页 img
返回顶部~
返回顶部 img