MFC的串行化编程

上传人:ta****u 文档编号:164972330 上传时间:2022-10-26 格式:DOCX 页数:13 大小:19.85KB
收藏 版权申诉 举报 下载
MFC的串行化编程_第1页
第1页 / 共13页
MFC的串行化编程_第2页
第2页 / 共13页
MFC的串行化编程_第3页
第3页 / 共13页
资源描述:

《MFC的串行化编程》由会员分享,可在线阅读,更多相关《MFC的串行化编程(13页珍藏版)》请在装配图网上搜索。

1、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 不同而已

2、。在开始学习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 rializabl

3、e Objects)的文件读写。一般情况下,使用 CArchive 对对象进行读操作的过程如下:/示例代码2/定义文件对象和文件异常对象CFile file;CFileException fe;/以读方式打开文件if(!file.Open(filename,CFile:modeRead,&fe)fe.ReportError();return;/构建 CArchive 对象CArchive ar(&file,CArchive:load);ar obj1obj2obj3.objn;ar.Flush();/读完毕,关闭文件流ar.Close();file.Close();使用 CArchive 对对

4、象进行写操作的过程如下:/示例代码3/定义文件对象和文件异常对象CFile file;CFileException fe;/以读方式打开文件 if(!file.Open(filename,CFile:modeWrite|CFile:modeCreate,&fe)fe.ReportError();return;/构建 CArchive 对象CArchive ar(&file,CArchive:load);ar obj1obj2obj3.GetLength() != 0)Serialize(loadArchive); / load meloadArchive.Close();ReleaseFile

5、(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;同样,当用户选择菜单文件

6、/文件保存(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:s

7、hareExclusive, &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(saveArchi

8、ve); / 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从前面两段代码

9、可以看出,文件读和文件写的结构基本相同,并且最终都调用了 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派生类

10、也应该实现 这个缺省的Serialize函数,否则,系统在文件读写时只能调用CObject:Serialize,这个函数什么都不 做,当然也无法完成对特定对象的文件保存/载入工作。当然,用户也可以截获 ID_FILE_OPEN 等菜单, 实现自己的文件读写功能,但是这样的代码将变得非常烦琐,也不容易阅读。回到CMyDoc:Serialize函数。这个函数通过对ar对象的判断,决定当前是在读还是在写文件。由于AppWizard 不知道你的文档是干什么的,所以它不会给添加实际的文件读写代码。假设我们的文档中有三个对象m_Obj_a,m_Obj_b,m_Obj_c,那么实际的代码应该为:/示例代码

11、7void CMyDoc:Serialize(CArchive& ar)if (ar.IsStoring()ar m_Obj_a m_Obj_b m_Obj_a m_Obj_b m_Obj_c;可串行化对象(Serializable Object) 要利用示例代码7中的方式进行文件I/O的一个基本条件是:m_Obj_a等对象必须是可串行化的对象。一个可串行化对象的条件为: 这个类从CObject派生 该类实现了 Serialize函数 该类在定义时使用了 DECLARE_SERIAL 宏 在类的实现文件中使用了 IMPLEMENT_SERIAL 宏 这个类有一个不带参数的构造函数,或者某一个带

12、参数的构造函数所有的参数都提供了缺省参数这里,可串行化对象条件中没有包括简单类型,对于简单类型,CArchive基本都实现了运算符和 的重载,所以可以直接使用串行化方式进行读写。从 CObject 类派生串行化要求对象从 CObject 派生,或者从一个 CObject 的派生类派生。这个要求比较简单,因为几 乎所有的类(不包括CString)都是从CObject派生的,因此对于从MFC类继承的类都满足这个要求。 对于自己的数据类,可以指定它的基类为 CObject 来满足这个要求。实现 Serialize 函数Serialize 函数是对象真正保存数据的函数,是整个串行化的核心。其实现方法和

13、 CMyDoc:Serialize 一样,利用 CArchive:IsStoring 和 CArchive:IsLoading 判断当前的操作,并选择和来保存和 读取对象。使用 DECLARE_SERIAL 宏DECLARE_SERIAL 宏包括了 DECLARE_DYNAMIC 和 DECLARE_DYNCREATE 功能,它定义了一个类的 CRuntimeClass 相关信息,并实现了缺省的 operator 重载。实现了该宏以后, CArchive 就可以利用ReadObject和WriteObject来进行对象I/O,并能够在事先不知道类型的情况下从文件中读 对象。使用 IMPLEME

14、NT_SERIALDECLARE_SERIAL 宏和 IMPLEMENT_SERIAL 宏必须成对出现,否则 DECLARE_SERIAL 宏定义的实 体将无法实现,最终导致连接错误。缺省构造函数这是 CRuntimeClass:CreateObject 对对象的要求。特殊情况只通过Serialize函数对对象读写,而不使用ReadObject/WriteObject和运算符重载时,前面的可串 行化条件不需要,只要实现 Serialize 函数即可。对现存的类,如果它没有提供串行化功能,可以通过使用重载友元operator 来实现。例子:假设需要实现一个几何图形显示、编辑程序,支持可扩展的图形

15、功能。这里不想讨论具体图形系统 的实现,只讨论图像对象的保存和载入。基类 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:C

16、Picture(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 CPic

17、ture:Draw(CDC * pDC)/基类不实现绘图功能,由派生类实现void CPicture:Serialize(CArchive & ar)if(ar.IsLoading()ar m_nType;注意:由于 CRuntimeClass 要求这个对象必须能够被实例化,因此虽然 Draw 函数没有任何绘图操作, 这个类还是没有把它定义成纯虚函数。对象在CDocument派生类中的保存和文件I/O过程为了简化设计,在CDocument类派生类中,采用MFC提供的模板类CPtrList来保存对象。该对象定义 为:protected:CTypedPtrList m_listPictures;由

18、于CTypedPtrList和CPtrList都没有实现Serialize函数,因此不能够通过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 pPicture;TRACE(Read Object %dn,pPictu

19、re-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_

20、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. arm_ptStart.xm_ptStart.ym_ptEnd.xm_ptEnd.y;12. else13. arm_ptStart.xm_ptStart.ym_ptEnd.xm_ptEnd.y;14. 15. 16. 在 CPP 文件中增加17. IMPLEMENT_SERIAL(CLine,CPicture,TYPE_LINE);这样定义的CLine就具有串行化功能,其他图形类可以类似定义。

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

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

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


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