RTTI运行时类型识别与类对象的动态创建

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

RTTI运行时类型识别CRuntimeClass是MFC专用的。CRuntimeClass在文件AFX.H中声明,它是用来串起MFC从COBJECT继承下来的所有类。也可以把自己写的类加入这个链表。structCRuntimeClass{//AttributesLPCSTRm_lpszClassName;//类名intm_nObjectSize;//类对象大小UINTm_wSchema;//分类编号(对不可分类的类,该值为-1)CObject*(PASCAL*m_pfnCreateObject)();//NULL=abstractclassCRuntimeClass*m_pBaseClass;//基类指针,但这里指针一定是指向父亲的,而不会指向祖父//CRuntimeClassobjectslinkedtogetherinsimpleliststaticCRuntimeClass*pFirstClass;//classlist的链表头。注意这个与基类指针不同。并且,该对象是个静态变量,所有CRuntimeClass对象共享CRuntimeClass*m_pNextClass;//链表中紧跟当前对象的下一个对象。与当前对象不一定有继承关系};特别注意:该struct使用了链表的概念,但是该链表与常规的数据结构链表是不太一样的。该链表每次新加入的节点都是放在链表头上的,类似栈。所以pFirstClass是随着每次新节点的加入一直在更新的,pFirstClass必然指向新加入的节点。而m_pNextClass则指向前一个加入的节点。如下图:首先初始化staticCRuntimeClass*pFirstClass为NULL。①最开始加入链表的是CObject。此时:在_IMPLEMENT_RUNTIMECLASS宏中先直接设置m_pBaseClass:#m_pBaseClass=NULL;然后在_IMPLEMENT_RUNTIMECLASS宏中调用AFX_CLASSINIT的构造函数设置m_pNextClass与pFirstClass:(这两者是先m_pNextClass后pFirstClass)#m_pNextClass=pFirstClass=NULL;#pFirstClass=CObject;②然后CCmdTarget加入链表。数据更新顺序同上:#m_pBaseClass=CObject;#m_pNextClass=pFirstClass=CObject;#pFirstClass=CCmdTarget;③接着CWinThread加入链表。数据更新顺序同上:#m_pBaseClass=CCmdTarget;#m_pNextClass=pFirstClass=CCmdTarget;#pFirstClass=CWinThread;每一个类都拥有这样一个static的CRuntimeClass成员变量。由于每个类都有static的CRuntimeClass成员变量,所以每个类的对象都是引用以及修改本类的static的CRuntimeClass成员变量,而不会将父类或者子类的修改掉。(父类与子类中的static同名成员变量是会造成“覆盖”的,该覆盖指的是引用时若不加域名直接使用,则使用的是本类的,而不会引用父类的。但实际上在内存中父类的static同名成员变量是依然存在的)每个static的CRuntimeClass成员变量都有一定的命名规则(在CRuntimeClass中采用的方法是在每个类的类名之前冠以class作为它的名称,如CView的名称为classCView),然后,经由某种手段将整个类别库构造好之后,「类别型录」能呈现类似这样的风貌:注意是每个类共享一个CRuntimeClass成员变量。例:CCmdTargetcmd1,cmd2;CWinThreadthread;上面两个类定义了三个对象。其中:①cmd1与cmd2共享一个CRuntimeClass成员变量。所以cmd1与cmd2所拥有的CRuntimeClass成员变量是同一个。②thread单独使用一个CRuntimeClass成员变量。thread所使用的这个CRuntimeClass成员变量与cmd1、cmd2共享的那个CRuntimeClass成员变量不是同一个。③pFirstClass是CRuntimeClass结构体中的static变量,所以所有的对象都共享pFirstClass。因此,cmd1、cmd2、thread三者共享CRuntimeClass结构体中的static变量pFirstClass。对于CView,其CView.hclassCView:publicCWnd{DECLARE_DYNAMIC(CView)}CView.cppIMPLEMENT_DYNAMIC(CsdiTestView,CView)其中的两个宏DECLARE_DYNAMIC与IMPLEMENT_DYNAMIC展开后,代码如下://*****************************************************************************#defineDECLARE_DYNAMIC(class_name)\public:\staticCRuntimeClassclass##class_name;\virtualCRuntimeClass*GetRuntimeClass()const;#defineIMPLEMENT_DYNAMIC(class_name,base_class_name)\_IMPLEMENT_RUNTIMECLASS(class_name,base_class_name,0xFFFF,NULL)*****************************************************************************//①出现在宏定义之中的##,用来告诉编译器,把两个字符串系在一起。如果你这么使用此宏:DECLARE_DYNAMIC(CView)编译器前置处理器为你做出的码是:public:staticCRuntimeClassclassCView;//静态成员变量,所有该类对象都共享该变量virtualCRuntimeClass*GetRuntimeClass()const;②IMPLEMENT_DYNAMIC宏之中又使用了一个_IMPLEMENT_RUNTIMECLASS宏,之所以这样做是因为_IMPLEMENT_RUNTIMECLASS宏在动态创建时还要用到。_IMPLEMENT_RUNTIMECLASS宏定义://*****************************************************************************#define_IMPLEMENT_RUNTIMECLASS(class_name,base_class_name,wSchema,pfnNew)\staticchar_lpsz##class_name[]=#class_name;\CRuntimeClassclass_name::class##class_name={\_lpsz##class_name,sizeof(class_name),wSchema,pfnNew,\RUNTIME_CLASS(base_class_name),NULL};\staticAFX_CLASSINIT_init_##class_name(&class_name::class##class_name);\CRuntimeClass*class_name::GetRuntimeClass()const\{return&class_name::class##class_name;}\*****************************************************************************//③其中又有RUNTIME_CLASS宏,该宏用于取指定类的静态CRuntimeClass对象地址。由于在上面代码中调用该宏是RUNTIME_CLASS(base_class_name),NULL};所以传入的参数是base_class_name,从而获取的地址是基类(即父类)的静态CRuntimeClass对象地址。其定义如下://*****************************************************************************#defineRUNTIME_CLASS(class_name)\(&class_name::class##class_name)*****************************************************************************//④看起来整个IMPLEMENT_DYNAMIC内容好象只是指定初值,不然,其曼妙处在于它所使用的一个structAFX_CLASSINIT,定义如下://*****************************************************************************structAFX_CLASSINIT{AFX_CLASSINIT(CRuntimeClass*pNewClass);};*****************************************************************************//这表示它有一个构造函数(别惊讶,C++的struct与class都有构造式),定义如下:AFX_CLASSINIT::AFX_CLASSINIT(CRuntimeClass*pNewClass){pNewClass-m_pNextClass=CRuntimeClass::pFirstClass;CRuntimeClass::pFirstClass=pNewClass;}很明显,此构造式负责linkedlist的串接工作。即将所有对象//inheaderfileclassCView:publicCWnd{DECLARE_DYNAMIC(CView)...};//inimplementationfileIMPLEMENT_DYNAMIC(CView,CWnd)上述的码展开来成为://头文件classCView:publicCWnd{public:staticCRuntimeClassclassCView;\virtualCRuntimeClass*GetRuntimeClass()const;//展开后定义了一个CRuntimeClass静态对象以及该对象的获取函数//静态成员变量classCView,所有该类对象都共享该变量//获取函数在这里仅仅是声明,具体实现需要在CPP中进行...};//实现staticchar_lpszCView[]=CView;//CRuntimeClass的第一个成员变量//注意这里定义了一个static的字符串,下面传参传入的就是这个字符串。这样做会使得所有的该类成员名称都相同CRuntimeClassCView::classCView={_lpszCView,sizeof(CView),0xFFFF,NULL,&CWnd::classCWnd,NULL};//该行代码用于为定义的CRuntimeClass对象classCView赋值。因为CRuntimeClass是个结构体,所以可以用{}将所有的值包含在内并直接使用=来进行赋值。//注意这种赋值方式仅仅会为结构体的常规成员变量赋值,而static变量与函数都是单独存储在另一片内存区的,所以不会被赋值。staticAFX_CLASSINIT_init_CView(&CView::classCView);CRuntimeCl

1 / 9
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功