新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论高级C/C++编程、代码重构(Refactoring)、极限编程(XP)、泛型编程等话题
    [返回] 计算机科学论坛计算机技术与应用『 C/C++编程思想 』 → [转帖]MFC CObject浅析 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 2714 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: [转帖]MFC CObject浅析 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     一分之千 帅哥哟,离线,有人找我吗?射手座1984-11-30
      
      
      威望:1
      等级:研一(随老板参加了WWW大会还和Tim Berners-Lee合了影^_^)
      文章:632
      积分:4379
      门派:XML.ORG.CN
      注册:2006/12/31

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给一分之千发送一个短消息 把一分之千加入好友 查看一分之千的个人资料 搜索一分之千在『 C/C++编程思想 』的所有贴子 引用回复这个贴子 回复这个贴子 查看一分之千的博客楼主
    发贴心情 [转帖]MFC CObject浅析

    FMD开发文集 -- MFC CObject浅析
    作者:冯明德

    CObject是大部分的MFC类的基类 为了完成MFC类的判断、动态生成、序列化等特殊功能,CObject中添加了特定的处理。 为了进一步增强对MFC类对象的理解,在此对CObject源码及相关宏定义进行分析。 (所附代码并非原始代码,为说明问题而作了删减。) 主要介绍了以下几方面内容:

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

    一.CObject简要声明

    class CObject
    {
    public:
     virtual CRuntimeClass* GetRuntimeClass() const;
     virtual ~CObject();
     
     void* PASCAL operator new(size_t nSize);
     void* PASCAL operator new(size_t, void* p);
     void PASCAL operator delete(void* p);
     void PASCAL operator delete(void* p, void* pPlace);


    #if defined(_DEBUG) //调试模式用,多了nLine参数,用于保存原码行号。
     void* PASCAL operator new(size_t nSize, LPCSTR lpszFileName, int nLine);
     void PASCAL operator delete(void *p, LPCSTR lpszFileName, int nLine);
    #endif

    protected:
     CObject();
    private:
     CObject(const CObject& objectSrc);
     void operator=(const CObject& objectSrc);

    // Attributes
    public:
     BOOL IsSerializable() const;
     BOOL IsKindOf(const CRuntimeClass* pClass) const;

    // Overridables
     virtual void Serialize(CArchive& ar);

    #if defined(_DEBUG) //调试模式下用
     virtual void AssertValid() const;
     virtual void Dump(CDumpContext& dc) const;
    #endif

    public:
     static const AFX_DATA CRuntimeClass classCObject;
     static CRuntimeClass* PASCAL _GetBaseClass();

    };
    在此声明中很多都是纯虚函数,定义的一个一般对象的"界面"

    二.CRuntimeClass结构

    在CObject中包含一个静态成员变量static CRuntimeClass classCObject;

    它是MFC内部用来管理类的重要结构,记录了很多对象所属类的重要信息,通过它在运行时完成对类的管理。 很多内部管理成员函数及宏定义都建立在CRuntimeClass的基础上的。 struct CRuntimeClass
    {
     //类名称
     LPCSTR m_lpszClassName;
     //大小
     int m_nObjectSize;
     //版本
     UINT m_wSchema;
     CObject* (PASCAL* m_pfnCreateObject)(); // NULL => abstract class
     //指向基类CRuntimeClass的指针,用于在运行时记录类继承关系。
    #ifdef _AFXDLL
     CRuntimeClass* (PASCAL* m_pfnGetBaseClass)();
    #else
     CRuntimeClass* m_pBaseClass;
    #endif

    // Operations
     //建立对象
     CObject* CreateObject();
     //派生判断
     BOOL IsDerivedFrom(const CRuntimeClass* pBaseClass) const;

    // Implementation
     //存储
     void Store(CArchive& ar) const;
     //读入
     static CRuntimeClass* PASCAL Load(CArchive& ar, UINT* pwSchemaNum);
     // CRuntimeClass objects linked together in simple list
     CRuntimeClass* m_pNextClass;       // linked list of registered classes
    };


    三.RUNTIME_CLASS

    RUNTIME_CLASS(class_name)用于返回指向运行时类信息结构的指针,定义如下: #define RUNTIME_CLASS(class_name) ((CRuntimeClass*)(&class_name::class##class_name))

    四.DYNAMIC支持

    在CObject 派生类中,可以获得动态"验证"支持,访问运行时类信息
    方法:
    声明时添加宏:DECLARE_DYNAMIC( class_name )
    实现时添加宏: IMPLEMENT_DYNAMIC

    原码分析:
    DECLARE_DYNAMIC(class_name)相当于在类中添加如下声明 : protected:
     static CRuntimeClass* PASCAL _GetBaseClass();
    public:
     //静态成员CRuntimeClass,给此派生类添加了运行时类信息,
     //这样就可以使用CRuntimeClass成员判断类信息了。
     //此成员名字格式为"class"+"类名",RUNTIME_CLASS()宏就是返回此结构的指针
     static const AFX_DATA CRuntimeClass class##class_name;
     virtual CRuntimeClass* 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_COMDAT const 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( const CRuntimeClass* pClass ) const判断类类型了。

    五.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 new class_name; }  //填写运行时类信息,与DYNAMIC不同的是,有pfnNew参数 
     IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF,   class_name::CreateObject)

    六.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_API friend 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);以实现类数据的保存及建立后读入。 从而实现类的保存,及读入动态建立。


       收藏   分享  
    顶(0)
      




    ----------------------------------------------
    越学越无知

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/3/10 15:49:00
     
     GoogleAdSense射手座1984-11-30
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 C/C++编程思想 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/11/23 0:16:12

    本主题贴数1,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    93.994ms