CObject浅析(转)

FMD(http://www.fmdstudio.net)

MFC CObject浅析
1.CObject简要声明
2.CRuntimeClass结构
3.RUNTIME_CLASS
4.DYNAMIC支持
5.DYNCREATE支持
6.SERIAL支持

   CObject是大部分的MFC类的基类,主要是通过它实现:运行类信息、序列化、对象诊断输出、同集合类相兼容、运行时类信息等特殊功能,CObject中添加了特定的处理。为了进一步增强对MFC类对象的理解,在此对CObject源码及相关宏定义进行分析。在此声明中很多都是纯虚函数,定义的一个一般对象的“界面”。

1.CObject简要声明
class CObject{
public:

   //返回RUNTIME_CLASS(classObject);
    virtualCRuntimeClass* GetRuntimeClass()const; 

   virtual ~CObject();
    void* PASCALoperator new(size_t nSize); 
    void* PASCALoperator new(size_t, void* p);
    void PASCALoperator delete(void* p); 
    void PASCALoperator delete(void* p, void* pPlace);

    #ifdefined(_DEBUG)//调试模式用,多了nLine参数,用于保存原码行号。 
    oid* PASCALoperator new(size_t nSize, LPCSTR lpszFileName, int

                          nLine);
    void PASCALoperator delete(void *p, LPCSTR lpszFileName, int

                          nLine);
   #endif

protected:
   CObject();

private:
   CObject(const CObject& objectSrc);
    voidoperator=(const CObject& objectSrc);

public:
    BOOLIsSerializable() const;
    BOOLIsKindOf(const CRuntimeClass* pClass) const;
    virtual voidSerialize(CArchive& ar);
    #ifdefined(_DEBUG) //调试模式下用
    virtual voidAssertValid() const;
    virtual voidDump(CDumpContext& dc) const;
    #endif
public:
   //CObject实现这些功能绝大部分是通过它里面的CRuntimeClass对classObject
   //实现的。CObject不支持多重继承,即表示以CObject为基类的类层次中只能

    //有一个CObject基类。
   //因为CRuntimeClass对象的成员m_pBaseClass的关系。因为它只是一个单链表
    static constAFX_DATA CRuntimeClass classCObject; 

   //此函数返回一个RUNTIME_CLASS
    staticCRuntimeClass* PASCAL _GetBaseClass();

};

2.CRuntimeClass结构
   在CObject中包含一个静态成员变量:static CRuntimeClassclassCObject。CObject和CRuntimeClass是MFC中两个非常重要的类/结构,绝大部分MFC类都是以CObject做为基类,CRuntimeClass结构同CObject密不可分,了解它们对于深入理解MFC具有重要意义,它是MFC内部用来管理类的重要结构,记录了很多对象所属类的重要信息,通过它在运行时完成对类的管理。很多内部管理成员函数及宏定义都建立在CRuntimeClass的基础上的。每个从CObject中派生的类都有CRuntimeClass对象同它关联完成在运行时得到类实例的信息或者是它的基类。要想使用CRuntimeClass结构得到运行时类信息,必须在你的类中包DECLARE_DYNAMIC
/IMPLEMENT_DYNAMIC

DECLARE_DYNCREATE/IMPLEMENT_DYNCREATE、DECLARE_SERIAL/IMPLEMENT_SERIAL。但你的类必须是从CObject派生的才能使用这些宏。

struct CRuntimeClass{   
   LPCSTRm_lpszClassName;//类名,一般指包含CRuntimeClass对象的类的名称 
   intm_nObjectSize;//包含CRuntimeClass对象类sizeof大小,不包括分配内存 
   UINTm_wSchema; //装载类的版本号

   //指向基类CRuntimeClass的指针,用于在运行时记录类继承关系。
   CObject*(PASCAL* m_pfnCreateObject)(); 
   #ifdef_AFXDLL 
   CRuntimeClass* (PASCAL*m_pfnGetBaseClass)();
   #else 
   //m_pBaseClass指针函数是MFC运行时确定类层次关键,它是一个简单单向链表
   CRuntimeClass*m_pBaseClass;
   #endif

   CObject*CreateObject(); //CObject 派生类运行时动态建立的能力
   //使用 m_pBaseClass或m_pfnGetBaseClass遍历整个类层次确定是否

   //pBaseClass指向的类是基类
   //使用它可以判断某类是否是从pBaseClass指向的类在派生来
    BOOLIsDerivedFrom(const CRuntimeClass* pBaseClass) const;

    voidStore(CArchive& ar) const; //读入
    staticCRuntimeClass* PASCAL Load(CArchive& ar, UINT*pwSchemaNum);
   CRuntimeClass* m_pNextClass;
};

3.RUNTIME_CLASS

  RUNTIME_CLASS(class_name)用于返回指向运行时类信息结构的指针 
   定义如下:
    #defineRUNTIME_CLASS(class_name) ((CRuntimeClass*)(&class_name::class##class_name))
   即得到类中的CRuntimeClass对象指针,显而易见,如果没有基类你用IMPLEMENT_DYNAMIC时将得到一个编译错误。除非你象CObject一样不用DECLARE_DYNAMIC而定义和实现了这些函数,CObject中的GetBaseClass只是简单的返回NULL。

4.DYNAMIC支持

在CObject派生类中,可以获得动态"验证"支持,访问运行时类信息的

方法:

声明时添加宏:DECLARE_DYNAMIC( class_name)
实现时添加宏: IMPLEMENT_DYNAMIC
原码分析:

// 定义宏
DECLARE_DYNAMIC(class_name)相当于在类中添加如下声明
protected:
    staticCRuntimeClass* PASCAL _GetBaseClass();
public:
   //静态成员CRuntimeClass,给此派生类添加了运行时类信息,这样就可以使用CRuntimeClass成员判断    //类信息了,此成员名字格式为"class"+"类名",RUNTIME_CLASS()宏就是返回此结构的指针
    static constAFX_DATA CRuntimeClass class##class_name;
    virtualCRuntimeClass* GetRuntimeClass() const;

// 实现宏
IMPLEMENT_DYNAMIC:
#define IMPLEMENT_DYNAMIC(class_name, base_class_name)
IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF,NULL)
#define IMPLEMENT_RUNTIMECLASS(class_name, base_class_name,wSchema, pfnNew)
   CRuntimeClass* PASCAL class_name::_GetBaseClass(){
       return RUNTIME_CLASS(base_class_name);
      //初始化本类的运行时信息,依次为类名、大小,版本 ,NULL,基类
    AFX_COMDATconst AFX_DATADEF CRuntimeClass class_name::class##class_name = {#class_name,     sizeof(class class_name), wSchema, pfnNew,&class_name::_GetBaseClass, NULL };
   //返回运行时类信息,重载了CObject的GetRuntimeClass
   //使得CObject中声明的接口对具体的派生类有效
   CRuntimeClass*  class_name::GetRuntimeClass()const{
       return RUNTIME_CLASS(class_name);
    }

   有了这些,就可以使用RUNTIME_CLASS()宏,以及用BOOL IsKindOf( constCRuntimeClass* pClass ) const判断类类型了。

5.DYNCREATE支持

类的实例动态生成支持,对于使用DECLARE_DYNCREATE要注意的是类必须要有一个无参数的缺省构造函数。

方法:

添加声明:DECLARE_DYNCREATE( class_name)

添加实现:IMPLEMENT_DYNCREATE( class_name,base_class_name )

原码分析:

DECLARE_DYNCREATE(class_name )
#define DECLARE_DYNCREATE(class_name) //具有DYNAMIC支持DECLARE_DYNAMIC(class_name)
static CObject* PASCAL CreateObject();//用以在动态的建立对象

IMPLEMENT_DYNCREATE(class_name,base_class_name):
#define IMPLEMENT_DYNCREATE(class_name, base_class_name)//动态建立对象
CObject* PASCAL class_name::CreateObject() {
    return newclass_name;
 }
//填写运行时类信息,与DYNAMIC不同的是,有pfnNew参数
IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF,class_name::CreateObject)

6.SERIAL支持

将对象储存,以及读取建立对象支持

方法:

添加声明:DECLARE_SERIAL( class_name)

添加实现:IMPLEMENT_SERIAL( class_name,base_class_name, wSchema)

原码分析

DECLARE_SERIAL( class_name ):
#define DECLARE_SERIAL(class_name) //动态生成支持
_DECLARE_DYNCREATE(class_name) //文档操作符
    AFX_APIfriend CArchive& AFXAPI operator>>(CArchive& ar,class_name* &pOb); 

IMPLEMENT_SERIAL(class_name, base_class_name,wSchema):
#define IMPLEMENT_SERIAL(class_name, base_class_name, wSchema)//动态生成支持
    CObject*PASCAL class_name::CreateObject() {
       return new class_name;
    }
  //填写运行时类信息,包括版本号,生成函数指针
_IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema,class_name::CreateObject) AFX_CLASSINIT_init_##class_name(RUNTIME_CLASS(class_name)); //文档支持实现
   CArchive& AFXAPI operator>>(CArchive& ar, class_name*&pOb) {
       pOb = (class_name*) ar.ReadObject(RUNTIME_CLASS(class_name));
       return ar;
    }
   在派生类中重载virtual void Serialize(CArchive&ar);以实现类数据的保存及建立后读入。
   第一级的宏是DECLARE_DYNAMIC/IMPLEMENT_DYNAMIC,它允许你在运行时处理类名和类层次中的位置,允许你做有意义的诊断Dump。
   第二级的宏是DECLARE_SERIAL/IMPLEMENT_SERIAL,它包括第一级宏所有的功能,允许你进行对象的序列化。
   DECLARE_DYNAMIC定义了运行时类对象,而IMPLEMENT_DYNAMIC是实现,thatlooks like as below:
class CObject{
     staticCRuntimeClass m_object; // 定义在DECLARE_DYNAMIC
};

    //Implementations
   CRuntimeClass CObject::m_object; //实现在IMPLEMENT_DYNAMIC

    CObject作为根,它是不应该存在运行时对象m_object的,可以用NULL表示CObject,这样在指针链表中比较方便。声明和实现是一对的,没有声明就没实现。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值