Chinaunix首页 | 论坛 | 博客
  • 博客访问: 16497847
  • 博文数量: 5645
  • 博客积分: 9880
  • 博客等级: 中将
  • 技术积分: 68081
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-28 13:35
文章分类

全部博文(5645)

文章存档

2008年(5645)

我的朋友

分类:

2008-04-28 20:56:51

下载本文示例代码
  一、概述  本文对MFC动态创建对象的方法做了一点阐述,给出了一些我认为存在的问题及相应的解决方法,不当及不足之处请各位不吝赐教。这里指的动态创建指给定一个类的名字(字符串),创建出相应的类的实例,类似于java里面的反射机制。  二、问题描述  对于给定的类,我们可以采取 CSampClass *m_pSampClass=new CSampClass  的方法,或稍微麻烦一点 CRuntimeClass *m_pRuntimeClass=RUNTIME_CLASS(CSampClass);m_pSampClass=(CSampClass *)m_pRuntimeClass->CreateObject();   我想大家都会毫不犹豫的选择第一种方法,这里给出第二种方法,只是为了下面叙述的方便。  现在给定的是一个类名字符串"CSampClass",我们当然不能直接用CSampClass *m_pSampClass=new "CSampClass"的方法创建出对象来。同样第二种方法也不行,但它给我们提供了另外一种思路:利用MFC的动态创建机制。  根据动态创建机制,我们需要在我们的类中加入DECLARE_DYNACREATE和IMPLEMEN_DYNACREATE宏,这两个宏的作用是在我们的类中加入一个CRuntimeClass类型的静态成员变量,然后将其加入一张链表中,构成我们的运行时类别信息表,以支持类的RTTI、DYNACREATE以及SERILIZE。  现在来看看CRuntimeClass里面到底有些什么东西,以下是其结构,来自MSDN. struct CRuntimeClass{ LPCSTR m_lpszClassName; int m_nObjectSize; UINT m_wSchema; CObject *(PASCAL *m_pfnCreateObject)(); CRuntimeClass *m_pBaseClass; CObject *CreateObject(); BOOL IsDerivedFrom(Const CRuntimeClass *pBaseClass) Const;}  其中,m_lpszClassName是对应的类名,m_pBaseClass是基类对应的CRuntimeClass结构,利用CreateObject我们就能够构建出对应类的实例来。  提到CRuntimeClass,我们不得不提到一个很重要的宏RUNTIME_CLASS,它接受一个类,并返回该类对应的CRuntimeClass结构,那么看到这里我们不难理解上面创建对象的 第二种方法,并且我们的动态创建好象也有了眉目:我们只需要遍历CRuntimeClass链表,把每个接点的m_lpszClassName和给定的类名字符串比较,如果相等,调用该接点的CreateObject()即可。  事情到此好象已经完了,真的那么简单吗?  我们再来检查一下,遍历链表,我们需要知道链表的头吧。头在哪里?RUNTIME_CLASS宏只是提供了我们给定的宏的CRuntimeClass结构,该结构并不是我们所要的头。并且CRuntimeClass结构也没为遍历整个链表提供足够的信息,m_pBaseClass只是为我们提供了按继承关系进行遍历的手段,但这无法支持对整个链表的遍历。好不容易走到这里,线索似乎又断了。  没办法,翻翻侯捷老师的深入浅出MFC吧。里面P97页讲到动态创建时,用到的CRuntimeClass结构如下: struct CRuntimeClass{ LPCSTR m_lpszClassName; int m_nObjectSize; UINT m_wSchema; CObject *(PASCAL *m_pfnCreateObject)(); CRuntimeClass *m_pBaseClass; CObject *CreateObject(); BOOL IsDerivedFrom(Const CRuntimeClass *pBaseClass) Const;  static CRuntimeClass *m_pFirstClass; CRuntimeClass *m_pNextClass;}  看到最后两个字段,我们不难推想出侯老师用的动态创建算法,不知道微软把这两个字段藏到什么地方去了。  后来看侯捷老师在深入浅出MFC中介绍SERILIZE时,在P388页有这么一段代码(我自己稍做改编,伪码),很给我启发: CRuntimeClass *CRuntimeClass::Load(CString szClassName){ CRuntimeClass *pClass=NULL; AFX_MODULE_STATE pModuleState=afxGetModuleState(); ASSERT(!pModuleState->m_classList.IsEmpty()); //我加的断言,调试用 for (pClass=pModuleState->m_classList;pClass!=NULL;pClass=pClass->m_pNextClass)  if (lstrcmpa(szClassName,pClass->m_lpszClassName)==0)   return pClass;  return NULL;}   这段代码好象是说所有的CRuntimeClass结构都放在pModuleState->m_classList,但我在调试是时断言总是不成立,并且pClass=pClass->m_pNextClass这一句也让我困惑不已,MFC里面的CRunTimeClass哪里来的m_pNextClass字段?请高手指点。  三、解决办法  既然在MFC里面好象直接找不到办法(也许是我暂时没发现,请高手指教),我们可以采用间接的办法,自己 写一个CRuntimeClassEX类,包装MFC里面的CRuntimeClass,另加两个字段: struct CRuntimeClassEX{ CRuntimeClass *m_pCRunTimeClass;  static CRuntimeClass *m_pFirstClass; CRuntimeClass *m_pNextClass; }  同样,需要包装DECLARE_DYNACREATE(DECLARE_DYNACREATEX)和IMPLEMEN_DYNACREATE(IMPLEMEN_DYNACREATEX)两个宏,具体请参见候捷老师在深入浅出MFC里面的方法。我们在动态创建时只需要遍历该链表,找到相应的CRuntimeClass,即可创建出我们的对象来。zmbbs=1;   一、概述  本文对MFC动态创建对象的方法做了一点阐述,给出了一些我认为存在的问题及相应的解决方法,不当及不足之处请各位不吝赐教。这里指的动态创建指给定一个类的名字(字符串),创建出相应的类的实例,类似于java里面的反射机制。  二、问题描述  对于给定的类,我们可以采取 CSampClass *m_pSampClass=new CSampClass  的方法,或稍微麻烦一点 CRuntimeClass *m_pRuntimeClass=RUNTIME_CLASS(CSampClass);m_pSampClass=(CSampClass *)m_pRuntimeClass->CreateObject();   我想大家都会毫不犹豫的选择第一种方法,这里给出第二种方法,只是为了下面叙述的方便。  现在给定的是一个类名字符串"CSampClass",我们当然不能直接用CSampClass *m_pSampClass=new "CSampClass"的方法创建出对象来。同样第二种方法也不行,但它给我们提供了另外一种思路:利用MFC的动态创建机制。  根据动态创建机制,我们需要在我们的类中加入DECLARE_DYNACREATE和IMPLEMEN_DYNACREATE宏,这两个宏的作用是在我们的类中加入一个CRuntimeClass类型的静态成员变量,然后将其加入一张链表中,构成我们的运行时类别信息表,以支持类的RTTI、DYNACREATE以及SERILIZE。  现在来看看CRuntimeClass里面到底有些什么东西,以下是其结构,来自MSDN. struct CRuntimeClass{ LPCSTR m_lpszClassName; int m_nObjectSize; UINT m_wSchema; CObject *(PASCAL *m_pfnCreateObject)(); CRuntimeClass *m_pBaseClass; CObject *CreateObject(); BOOL IsDerivedFrom(Const CRuntimeClass *pBaseClass) Const;}  其中,m_lpszClassName是对应的类名,m_pBaseClass是基类对应的CRuntimeClass结构,利用CreateObject我们就能够构建出对应类的实例来。  提到CRuntimeClass,我们不得不提到一个很重要的宏RUNTIME_CLASS,它接受一个类,并返回该类对应的CRuntimeClass结构,那么看到这里我们不难理解上面创建对象的 第二种方法,并且我们的动态创建好象也有了眉目:我们只需要遍历CRuntimeClass链表,把每个接点的m_lpszClassName和给定的类名字符串比较,如果相等,调用该接点的CreateObject()即可。  事情到此好象已经完了,真的那么简单吗?  我们再来检查一下,遍历链表,我们需要知道链表的头吧。头在哪里?RUNTIME_CLASS宏只是提供了我们给定的宏的CRuntimeClass结构,该结构并不是我们所要的头。并且CRuntimeClass结构也没为遍历整个链表提供足够的信息,m_pBaseClass只是为我们提供了按继承关系进行遍历的手段,但这无法支持对整个链表的遍历。好不容易走到这里,线索似乎又断了。  没办法,翻翻侯捷老师的深入浅出MFC吧。里面P97页讲到动态创建时,用到的CRuntimeClass结构如下: struct CRuntimeClass{ LPCSTR m_lpszClassName; int m_nObjectSize; UINT m_wSchema; CObject *(PASCAL *m_pfnCreateObject)(); CRuntimeClass *m_pBaseClass; CObject *CreateObject(); BOOL IsDerivedFrom(Const CRuntimeClass *pBaseClass) Const;  static CRuntimeClass *m_pFirstClass; CRuntimeClass *m_pNextClass;}  看到最后两个字段,我们不难推想出侯老师用的动态创建算法,不知道微软把这两个字段藏到什么地方去了。  后来看侯捷老师在深入浅出MFC中介绍SERILIZE时,在P388页有这么一段代码(我自己稍做改编,伪码),很给我启发: CRuntimeClass *CRuntimeClass::Load(CString szClassName){ CRuntimeClass *pClass=NULL; AFX_MODULE_STATE pModuleState=afxGetModuleState(); ASSERT(!pModuleState->m_classList.IsEmpty()); //我加的断言,调试用 for (pClass=pModuleState->m_classList;pClass!=NULL;pClass=pClass->m_pNextClass)  if (lstrcmpa(szClassName,pClass->m_lpszClassName)==0)   return pClass;  return NULL;}   这段代码好象是说所有的CRuntimeClass结构都放在pModuleState->m_classList,但我在调试是时断言总是不成立,并且pClass=pClass->m_pNextClass这一句也让我困惑不已,MFC里面的CRunTimeClass哪里来的m_pNextClass字段?请高手指点。  三、解决办法  既然在MFC里面好象直接找不到办法(也许是我暂时没发现,请高手指教),我们可以采用间接的办法,自己 写一个CRuntimeClassEX类,包装MFC里面的CRuntimeClass,另加两个字段: struct CRuntimeClassEX{ CRuntimeClass *m_pCRunTimeClass;  static CRuntimeClass *m_pFirstClass; CRuntimeClass *m_pNextClass; }  同样,需要包装DECLARE_DYNACREATE(DECLARE_DYNACREATEX)和IMPLEMEN_DYNACREATE(IMPLEMEN_DYNACREATEX)两个宏,具体请参见候捷老师在深入浅出MFC里面的方法。我们在动态创建时只需要遍历该链表,找到相应的CRuntimeClass,即可创建出我们的对象来。zmbbs=1; 下载本文示例代码


MFC中动态创建对象的一点思考MFC中动态创建对象的一点思考MFC中动态创建对象的一点思考MFC中动态创建对象的一点思考MFC中动态创建对象的一点思考MFC中动态创建对象的一点思考MFC中动态创建对象的一点思考MFC中动态创建对象的一点思考MFC中动态创建对象的一点思考MFC中动态创建对象的一点思考MFC中动态创建对象的一点思考MFC中动态创建对象的一点思考MFC中动态创建对象的一点思考MFC中动态创建对象的一点思考MFC中动态创建对象的一点思考
阅读(204) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~