串行化(Serialization)

        
        //示例代码6
        void CMyDoc::Serialize(CArchive& ar)
        {
        	if (ar.IsStoring())
        	{
        		// TODO: add storing code here
        	}
        	else
        	{
        		// 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,那么实际的代码应该为:

        
        //示例代码7
        void CMyDoc::Serialize(CArchive& ar)
        {
            	if (ar.IsStoring())
            	{
            		ar << m_Obj_a << m_Obj_b << m_Obj_c;
            	}
            	else
            	{
            		ar >> m_Obj_a >> m_Obj_b >> m_Obj_c;
            	}
        }

可串行化对象(Serializable Object)

要利用VCkbase.com/document/viewdoc/?id=918#CODE7">示例代码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_SERIAL

DECLARE_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 > 1000
        
        const int TYPE_UNKNOWN = -1;
        class CPicture:public CObject
        {
            int 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_FILE
        static char THIS_FILE[] = __FILE__;
        #endif
        
        void CPicture::Draw(CDC * pDC)
        {
           //基类不实现绘图功能,由派生类实现
        }
        
        void CPicture::Serialize(CArchive & ar)
        {
            if(ar.IsLoading())
            {
                ar << m_nType;
            }else{
                ar >> m_nType;
            
            }
        }

共3页 首页 上一页 [1] [2] [3下一页 尾页>
相关信息
相关评论
字母检索 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z