MFC的运行时类型识别

来源:互联网 发布:html源码加密 编辑:程序博客网 时间:2024/06/03 19:05
转载自


http://www.cnblogs.com/zuibunan/archive/2012/09/10/2679078.html。感谢原作者醉步男的博客

类别型录网搭建的目的是为了实现所谓的"执行期类型识别",也就是在程序运行的时候识别出某个对象是否是某个类的实例(基类也可以)。这里还不是很明白为什么需要实现"执行期类型识别",这种技巧具体被应用在哪里。

例如在MFCCView继承于CWnd,那么可以进行这样的判断:

CView view;

bool result = view.IsKindOf(CWnd); // result == true

如上,通过调用IsKindOf函数,可以判断出view对象是一个CWnd类的实例。

   

MFC通过建立一张型录网来实现这样的功能。也就是把类登记到一个表中,传入特定的参数之后在这张表上进行查找比对,从而实现"执行期类型识别"。

具体说来比对过程如下:

为了在不同的对象和类之间互相比对,肯定类里得有一个特殊的标识才行,MFC通过为每个类添加一个CRuntimeClass类型的静态成员来作为这个标识。

注意这里是静态成员,其原因不言自明,如果是普通成员的话,不同的对象之间成员都不一样,无法实现比对。

   

每个类都有了特殊标识之后,仅仅能进行一对一的比对,也就是说只能进行CView.IsKindOf(CView)这样的操作,无法判断一个CView对象是否也是一个CWnd对象。

MFC实现这种功能的方法类似于链表的实现:链表中有一个指针专门指向它下一个成员的位置,遍历时依靠这个指针来不断指向下一个。

CRuntimeClass类包含一个指针叫m_pBaseClass,对于CView,它有一个CRuntimeClass成员(就是之前说的特殊标识),只要使得这个成员的m_pBaseClass指针指向CWndCRuntimeClass成员,那么就建立起了类似链表的结构。

当判断CView.IsKindOf(CWnd)时,首先判断CViewCRuntimeClass成员和CWndCRuntimeClass成员是不是一致,发现不一致之后,在CViewCRuntimeClass成员中根据m_pBaseClass来得到CView的父类CWndCRuntimeClass成员,之后再进行比对,发现是一致的,因此可以判断CView.IsKindOf(CWnd)为真。

   

下面介绍MFC中对上述机制的具体实现方法:

1.为每个类添加特定标识CRuntimeClass成员:

使用DECLARE_DYNAMIC宏:

class CView : public CWnd
{
        DECLARE_DYNAMIC(CView)

如上,使用了DECLARE_DYNAMIC宏之后,CView类中多了一个CRuntimeClass类型的静态成员 classCView(名为classXXXX,也就是在类名之前加一个class),也就是之前所说的具有比较功能的"特殊标识"

2.建立类别型录表:

也就是初始化classCView,使它的m_pBaseClass指针指向父类

IMPLEMENT_DYNCREATE(CView, CWnd)

如上,静态成员的初始化需要在实现文件中进行,在实现文件中使用了IMPLEMENT_DYNAMIC宏之后,classCViewm_pBaseClass指针指向了CWndclassCWnd成员

3.实现类型识别IsKindOf

this->IsKindOf(RUNTIME_CLASS(CWnd))

如上,IsKindOf函数的参数有点特别,是一个RUNTIME_CLASS宏,这个宏的功能其实非常简单,其实就是一个函数调用:RUNTIME_CLASS(CWnd)等价于CWnd::GetThisClass(),这个函数的返回值就是CWndCRuntimeClass成员,也就是CWnd的"特殊标识",把这个特殊标识传递给IsKindOf函数之后,事情就好办许多,逐个提取CView及其父类的CRuntimeClass成员与这个标识进行比对就可以达到判断的目的了。因为是静态变量,所以只存有一份拷贝,可以直接把指针作为比较时的参照。

0 0
原创粉丝点击