MFC六大机制之四:运行时类信息机制(RTTI)

来源:互联网 发布:lp网络公共广播系统 编辑:程序博客网 时间:2024/06/10 04:48

      首先得说明究竟什么是运行时类信息: 程序在运行时,得到对象的类信息以及所属类的继承层次关系RTTI(Run-Time Type Information,运行时类型信息),下边通过一个例子来说明

   1.建一个win32控制台程序。

   2.将stdafx.h 添加头文件<afxwin.h>。

   3.Project-->Settings菜单项中设置使用MFC库

   4.编写代码:

// Dynamic.cpp : Defines the entry point for the console application.//#include "stdafx.h"//定义支持运行时类信息的类class CAnimal:public CObject{DECLARE_DYNAMIC(CAnimal)};IMPLEMENT_DYNAMIC(CAnimal,CObject)class CDog:public CAnimal{DECLARE_DYNAMIC(CDog)};IMPLEMENT_DYNAMIC(CDog,CAnimal)int main(int argc, char* argv[]){CDog dog;if (dog.IsKindOf(RUNTIME_CLASS(CAnimal))){printf("dog is a CAnimal !\n");}else{printf("no no no !\n");}CRuntimeClass *pClass=dog.GetRuntimeClass();printf("类的名称:%s\n",pClass->m_lpszClassName);printf("类的大小:%d\n",pClass->m_nObjectSize);return 0;}

注意:

     1 派生自CObject

      2 添加动态创建的声明宏和实现宏

             DECLARE_DYNCREATE(theClass)

             IMPLEMENT_DYNCREATE(theClass,baseClass) 




为什么上边的程序可以做判断和输出类信息???   我们来做个宏代换,结果如下

// Dynamic.cpp : Defines the entry point for the console application.//#include "stdafx.h"//定义支持运行时类信息的类class CAnimal:public CObject{DECLARE_DYNAMIC(CAnimal)};IMPLEMENT_DYNAMIC(CAnimal,CObject)class CDog:public CAnimal{//DECLARE_DYNAMIC(CDog)public:static const AFX_DATA CRuntimeClass classCDog; virtual CRuntimeClass* GetRuntimeClass() const; };//IMPLEMENT_DYNAMIC(CDog,CAnimal)//IMPLEMENT_RUNTIMECLASS(CDog, CAnimal, 0xFFFF, NULL)AFX_COMDAT const AFX_DATADEF CRuntimeClass CDog::classCDog = {"CDog", sizeof(class CDog), 0xFFFF, NULL, RUNTIME_CLASS(CAnimal), NULL }; CRuntimeClass* CDog::GetRuntimeClass() const { //return RUNTIME_CLASS(CDog); return ((CRuntimeClass*)(&CDog::classCDog));} int main(int argc, char* argv[]){//判断CDog dog;if(dog.IsKindOf(RUNTIME_CLASS(CWnd))){printf("dog is  a CWnd!\n");}else{printf("dog is not a CWnd!\n");}//2 获取类的信息CRuntimeClass *pClass=dog.GetRuntimeClass();    printf("类的名称:%s\n",pClass->m_lpszClassName);printf("类的大小:%d\n",pClass->m_nObjectSize);return 0;}
分析:

 1. CDog有一个静态变量和一个虚函数:

classCDog-----类型是CRuntimeClass,的静态成员变量,保存本类信息和父类运行时类信息地址。

GetRuntimeClass------虚函数,作用是返回classCDog的地址

2. CRuntimeClass:用户可以使用该结构获取一个对象及其基类的运行时信息。

struct CRuntimeClass{LPCSTR m_lpszClassName;//类的名称int m_nObjectSize;//类的大小UINT m_wSchema; //类的版本 CObject* (PASCAL* m_pfnCreateObject)(); //NULL CRuntimeClass* m_pBaseClass;//父类的运行时类信息变量的地址                             ...}
结合我们编写的例子我们很容易看到,现在形成了一个类的信息链表,如下:
CDog::GetRuntimeClass()
          |->&classCDog
              |->类的名称,大小,版本等信息
              |->&classCAnimal
                    |->CAnimal类的名称、大小、版本等信息
                    |->&classCObject
                         |->CObject类的名称、大小版本等
                          |->NULL 

3. IsKindOf函数是怎么实现的???  加断点,f11进入函数内部,写出伪代码如下:

 BOOL CObject::IsKindOf(const CRuntimeClass* pClass) const    {         //classCDog的地址          CRuntimeClass* pClassThis = GetRuntimeClass();         return pClassThis->IsDerivedFrom(pClass);       pClassThis->IsDerivedFrom(pClass)       {            //classCDog的地址            const CRuntimeClass* pClassThis = this;    while (pClassThis != NULL)    {//比较                if (pClassThis == pBaseClass)return TRUE;        //获取父类的变量的地址pClassThis = pClassThis->m_pBaseClass;    }   return FALSE;     }  } 


原理:
       调用GetRuntimeClass获取&classCDog

       调用IsDerivedFrom()函数,在函数中,把&classCDog与参数的&classCWnd比较,如果相等,返回TRUE,表示对象属于该类,如果不相等,获取&classCAnimal,继续循环比较,直到&classCObject的父类的变量地址为空,最后,返回FALSE,表示对象不属于该类。



总结:

        其实简单的讲就是同通过GetRuntimeClass函数拿到本类的一个静态变量,该变量中保存这本类的信息,和父类的父类的运行时类信息变量的地址,形成一条类的信息链,通过遍历该链表查找类的信息。


    






0 0
原创粉丝点击