欢迎来到装配图网! | 帮助中心 装配图网zhuangpeitu.com!
装配图网
ImageVerifierCode 换一换
首页 装配图网 > 资源分类 > DOCX文档下载
 

MFC的串行化编程

  • 资源ID:164972330       资源大小:19.85KB        全文页数:13页
  • 资源格式: DOCX        下载积分:12积分
快捷下载 游客一键下载
会员登录下载
微信登录下载
三方登录下载: 微信开放平台登录 支付宝登录   QQ登录   微博登录  
二维码
微信扫一扫登录
下载资源需要12积分
邮箱/手机:
温馨提示:
用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)
支付方式: 支付宝    微信支付   
验证码:   换一换

 
账号:
密码:
验证码:   换一换
  忘记密码?
    
友情提示
2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

MFC的串行化编程

MFC的串行化编程收藏串行化是微软提供的用于对对象进行文件I/O的一种机制,该机制在框架(Frame)/文档(Document)/视 图(View)模式中得到了很好的应用。MFC 框架/文档/视图结构中的文件读写CFile是MFC类库中所有文件类的基类。所有MFC提供的文件I/O功能都和这个类有关。很多情况下, 大家都喜欢直接调用 CFile:Write/WriteHuge 来写文件,调用 CFile:Read/ReadHuge 来读文件。这 样的文件I/O其实和不使用MFC的文件I/O没有什么区别,甚至和以前的ANSI C的文件I/O也没有多 少差别,所差别的不外乎是调用的 API 不同而已。在开始学习C+ +的时候,大家一定对cin/cout非常熟悉,这两个对象使用非常明了的和运算符进 行I/O,其使用格式为:/示例代码1int i;cin i;/here do something to object icout i;使用这种方式进行 I/O 的好处时,利用运算符重载功能,可以用一个语句完成对一系列的对象的读写,而 不需要区分对象具体的类型。MFC提供了类CArchive,实现了运算符和的重载,希望按照前面cin 和cout的方式进行文件I/O。通过和CFile类的配合,不仅仅实现了对简单类型如int/float等的文件读 写,而且实现了对可序列化对象(Se rializable Objects)的文件读写。一般情况下,使用 CArchive 对对象进行读操作的过程如下:/示例代码2/定义文件对象和文件异常对象CFile file;CFileException fe;/以读方式打开文件if(!file.Open(filename,CFile:modeRead,&fe)fe.ReportError();return;/构建 CArchive 对象CArchive ar(&file,CArchive:load);ar >> obj1>>obj2>>obj3.>>objn;ar.Flush();/读完毕,关闭文件流ar.Close();file.Close();使用 CArchive 对对象进行写操作的过程如下:/示例代码3/定义文件对象和文件异常对象CFile file;CFileException fe;/以读方式打开文件 if(!file.Open(filename,CFile:modeWrite|CFile:modeCreate,&fe)fe.ReportError();return;/构建 CArchive 对象CArchive ar(&file,CArchive:load);ar << obj1<<obj2<<obj3.<<objn;ar.Flush();/写完毕,关闭文件流ar.Close();file.Close();可见,对于一个文件而言,如果文件内对象的排列顺序是固定的,那么对于文件读和写从形式上只有使用 的运算符的不同。在MFC的框架/文档/视图结构中,一个文档的内部对象的构成往往是固定的,这种情况 下,写到文件中时对象在文件中的布局也是固定的。因此CDocument利用其基类CObject提供的Ser ilize 虚函数,实现自动文档的读写。当用户在界面上选择文件菜单/打开文件(ID_FILE_OPEN)时,CWinApp派生类的OnFileOpen函数被 自动调用,它通过文档模板创建(MDI)/重用(SDI)框架、文档和视图对象,并最终调用CDocument:OnOpenDocument 来读文件, CDocument:OnOpenDocument 的处理流程如 下:/示例代码4BOOL CDocument:OnOpenDocument(LPCTSTR lpszPathName)if (IsModified()TRACE0("Warning: OnOpenDocument replaces an unsaved document.n"); CFileException fe;CFile* pFile = GetFile(lpszPathName, CFile:modeRead|CFile:shareDenyWrite, &fe); if (pFile = NULL)ReportSaveLoadException(lpszPathName, &fe,FALSE, AFX_IDP_FAILED_TO_OPEN_DOC); return FALSE;DeleteContents();SetModifiedFlag(); / dirty during de-serializeCArchive loadArchive(pFile, CArchive:load | CArchive:bNoFlushOnDelete);loadArchive.m_pDocument = this;loadArchive.m_bForceFlat = FALSE;TRYCWaitCursor wait;if (pFile->GetLength() != 0)Serialize(loadArchive); / load meloadArchive.Close();ReleaseFile(pFile, FALSE);CATCH_ALL(e)ReleaseFile(pFile, TRUE);DeleteContents(); / remove failed contentsTRYReportSaveLoadException(lpszPathName, e,FALSE, AFX_IDP_FAILED_TO_OPEN_DOC);END_TRYDELETE_EXCEPTION(e);return FALSE;END_CATCH_ALLSetModifiedFlag(FALSE); / start off with unmodifiedreturn TRUE;同样,当用户选择菜单文件/文件保存(ID_FILE_SAVE )或者文件/另存为(ID_FILE_SAVEAS)时,通 过CWinApp:OnFileSave和CWinApp:OnFileSaveAs 最终调用CDocument:OnSaveDocument, 这个函数处理如下:/示例代码5BOOL CDocument:OnSaveDocument(LPCTSTR lpszPathName)CFileException fe;CFile* pFile = NULL;pFile = GetFile(lpszPathName, CFile:modeCreate |CFile:modeReadWrite | CFile:shareExclusive, &fe);if (pFile = NULL)ReportSaveLoadException(lpszPathName, &fe,TRUE, AFX_IDP_INVALID_FILENAME);return FALSE;CArchive saveArchive(pFile, CArchive:store | CArchive:bNoFlushOnDelete); saveArchive.m_pDocument = this;saveArchive.m_bForceFlat = FALSE;TRYCWaitCursor wait;Serialize(saveArchive); / save mesaveArchive.Close();ReleaseFile(pFile, FALSE);CATCH_ALL(e)ReleaseFile(pFile, TRUE);TRYReportSaveLoadException(lpszPathName, e,TRUE, AFX_IDP_FAILED_TO_SAVE_DOC);END_TRYDELETE_EXCEPTION(e);return FALSE;END_CATCH_ALLSetModifiedFlag(FALSE); / back to unmodifiedreturn TRUE; / success从前面两段代码可以看出,文件读和文件写的结构基本相同,并且最终都调用了 CObject:Serialize 函数 完成对文档自己的读和写(参见注释中的save me和load me)。对于用AppWizard自动生成的MDI 和SDI,系统自动生成了这个函数的重载实现,缺省的实现为:/示例代码6void CMyDoc:Serialize(CArchive& ar)if (ar.IsStoring()/ TODO: add storing code hereelse/ TODO: add loading code here如果一个对VC非常熟悉的人,喜欢手工生成所有的代码,那么他提供的CDocument派生类也应该实现 这个缺省的Serialize函数,否则,系统在文件读写时只能调用CObject:Serialize,这个函数什么都不 做,当然也无法完成对特定对象的文件保存/载入工作。当然,用户也可以截获 ID_FILE_OPEN 等菜单, 实现自己的文件读写功能,但是这样的代码将变得非常烦琐,也不容易阅读。回到CMyDoc:Serialize函数。这个函数通过对ar对象的判断,决定当前是在读还是在写文件。由于AppWizard 不知道你的文档是干什么的,所以它不会给添加实际的文件读写代码。假设我们的文档中有三个对象m_Obj_a,m_Obj_b,m_Obj_c,那么实际的代码应该为:/示例代码 7void CMyDoc:Serialize(CArchive& ar)if (ar.IsStoring()ar << m_Obj_a << m_Obj_b << m_Obj_c;elsear >> m_Obj_a >> m_Obj_b >> m_Obj_c;可串行化对象(Serializable Object) 要利用示例代码7中的方式进行文件I/O的一个基本条件是:m_Obj_a等对象必须是可串行化的对象。一个可串行化对象的条件为: 这个类从CObject派生 该类实现了 Serialize函数 该类在定义时使用了 DECLARE_SERIAL 宏 在类的实现文件中使用了 IMPLEMENT_SERIAL 宏 这个类有一个不带参数的构造函数,或者某一个带参数的构造函数所有的参数都提供了缺省参数这里,可串行化对象条件中没有包括简单类型,对于简单类型,CArchive基本都实现了运算符和 的重载,所以可以直接使用串行化方式进行读写。从 CObject 类派生串行化要求对象从 CObject 派生,或者从一个 CObject 的派生类派生。这个要求比较简单,因为几 乎所有的类(不包括CString)都是从CObject派生的,因此对于从MFC类继承的类都满足这个要求。 对于自己的数据类,可以指定它的基类为 CObject 来满足这个要求。实现 Serialize 函数Serialize 函数是对象真正保存数据的函数,是整个串行化的核心。其实现方法和 CMyDoc:Serialize 一样,利用 CArchive:IsStoring 和 CArchive:IsLoading 判断当前的操作,并选择和来保存和 读取对象。使用 DECLARE_SERIAL 宏DECLARE_SERIAL 宏包括了 DECLARE_DYNAMIC 和 DECLARE_DYNCREATE 功能,它定义了一个类的 CRuntimeClass 相关信息,并实现了缺省的 operator 重载。实现了该宏以后, CArchive 就可以利用ReadObject和WriteObject来进行对象I/O,并能够在事先不知道类型的情况下从文件中读 对象。使用 IMPLEMENT_SERIALDECLARE_SERIAL 宏和 IMPLEMENT_SERIAL 宏必须成对出现,否则 DECLARE_SERIAL 宏定义的实 体将无法实现,最终导致连接错误。缺省构造函数这是 CRuntimeClass:CreateObject 对对象的要求。特殊情况只通过Serialize函数对对象读写,而不使用ReadObject/WriteObject和运算符重载时,前面的可串 行化条件不需要,只要实现 Serialize 函数即可。对现存的类,如果它没有提供串行化功能,可以通过使用重载友元operator <<和operator >>来实现。例子:假设需要实现一个几何图形显示、编辑程序,支持可扩展的图形功能。这里不想讨论具体图形系统 的实现,只讨论图像对象的保存和载入。基类 Cpicture 每个图形对象都从 CPicture 派生,这个类实现了串行化功能,其实现代码为:/头文件 picture.h#if !defined(_PICTURE_H_)#define _PICTURE_H_#if _MSC_VER > 1000#pragma once#endif / _MSC_VER > 1000const int TYPE_UNKNOWN = -1;class CPicture:public CObjectint m_nType;图形类别DECLARE_SERIAL(CPicture)public:CPicture(int m_nType=TYPE_UNKNOWN):m_nType(m_nType);int GetType()const return m_nType;virtual void Draw(CDC * pDC);void Serialize(CArchive & ar);#endif/cpp 文件 picture.cpp#include "stdafx.h"#include "picture.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE = _FILE_;#endifvoid CPicture:Draw(CDC * pDC)/基类不实现绘图功能,由派生类实现void CPicture:Serialize(CArchive & ar)if(ar.IsLoading()ar << m_nType;elsear >> m_nType;注意:由于 CRuntimeClass 要求这个对象必须能够被实例化,因此虽然 Draw 函数没有任何绘图操作, 这个类还是没有把它定义成纯虚函数。对象在CDocument派生类中的保存和文件I/O过程为了简化设计,在CDocument类派生类中,采用MFC提供的模板类CPtrList来保存对象。该对象定义 为:protected:CTypedPtrList m_listPictures;由于CTypedPtrList和CPtrList都没有实现Serialize函数,因此不能够通过ar << m_listPictures和 ar >> m_listPictures 来序列化对象,因此 CPictureDoc 的 Serialize 函数需要如下实现:void CTsDoc:Serialize(CArchive& ar)POSITION pos;if (ar.IsStoring()/ TODO: add storing code herepos = m_listPictures.GetHeadPosition();while(pos != NULL)ar << m_listPictures.GetNext (pos);else/ TODO: add loading code hereRemoveAll();CPicture * pPicture;dotryar >> pPicture;TRACE("Read Object %dn",pPicture->GetType ();m_listPictures.AddTail(pPicture);catch(CException * e)e->Delete ();break;while(pPicture != NULL);m_pCurrent = NULL;SetModifiedFlag(FALSE);实现派生类的串行化功能几何图形程序支持直线、矩形、三角形、椭圆等图形,分别以类 CLine、CRectangle、CTriangle 和 CEllipse实现。以类CLine为例,实现串行化功能:1. 从CPicture派生CLine,在CLine类定义中增加如下成员变量:2. CPoint m_ptStart,m_ptEnd;3. 在该行下一行增加如下宏:4. DECLARE_SERIAL(CLine)5. 实现 Serialize 函数6. void CLine:Serialize(CArchive & ar)8. CPicture:Serialize(ar);9. if(ar.IsLoading()10. 11. ar>>m_ptStart.x>>m_ptStart.y>>m_ptEnd.x>>m_ptEnd.y;12. else13. ar<<m_ptStart.x<<m_ptStart.y<<m_ptEnd.x<<m_ptEnd.y;14. 15. 16. 在 CPP 文件中增加17. IMPLEMENT_SERIAL(CLine,CPicture,TYPE_LINE);这样定义的CLine就具有串行化功能,其他图形类可以类似定义。

注意事项

本文(MFC的串行化编程)为本站会员(ta****u)主动上传,装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知装配图网(点击联系客服),我们立即给予删除!

温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!