MFC RTTI 实现

 

MFC RTTI 实现

  ——摘自侯俊杰《深入浅出MFC》

 

1.为了支持RTTI,MFC引入了CRuntimeClass的定义,定义如下:

struct CRuntimeClass

{

    //Attributes

    LPCSTR m_lpszClassName;

    int m_nObjectSize;

    UINT m_wSchema;//schema number of the loaded class

    CObject* (PASCAL* m_pfnCreateObject)();//NULL => abstract class // 存放函数指针,用于动态创建对象

    CRuntimeClass *m_pBaseClass;

 

    //调用m_pfnCreateObject动态创建对象

    CObject* CreateObject();

 

 

    //CRuntimeClass objects linked together in simple list

    static CRuntimeClass* pFirstClass;//start of class list

    CRuntimeClass* m_pNextClass;//linked list of registerd classes

};

 

2. DECLARE_DYNAMIC/IMPLEMENT_DYNAMIC


DECLARE_DYNAMIC定义为(.h):

#define DECLARE_DYNAMIC(class_name)/

public:/

    static CRuntimeClass class##class_name;/

    virtual CRuntimeClass* GetRuntimeClass()const;

 

例如:

DECLARE_DYNAMIC(CView)

预处理后的代码实际为:

public:

    static CRuntimeClass classCView ;

    virtual CRuntimeClass* GetRuntimeClass()const;

    //给我们定义了一个静态变量classCView和声明了一个虚函数GetRuntimeClass

    //正是使用classCView 来实现了RTTI功能。

 

IMPLEMENT_DYNAMIC宏定义为(.cpp):

#define IMPLIMENT_DYNAMIC(class_name,base_class_name)/

       _IMPLIMENT_RUNTIMECLASS(class_name,base_class_name,0xFFFF,NULL)

 

IMPLIMENT_RUNTIMECLASS宏定义如下:

#define IMPLIMENT_RUNTIMECLASS(class_name,base_class_name,wSchema,pfnNew)/

    static char _lpsz##class_name[] = #class_name;/

    CRuntimeClass class_name::class##class_name = {/

        _lpsz##class_name,sizeof(class_name),wSchema,pfnNew,RUNTIME_CLASS(base_class_name),NULL}/

    static AFX_CLASSINIT _init_##class_name(&class_name::class##class_name);/

    CRuntimeClass* class_name::GetRuntimeClass()const/

    {return &class_name::class##class_name;}/

 

RUNTIME_CLASS宏,定义如下:

#define RUNTIME_CLASS(class_name)/

    (&class_name::class##class_name)

 

看起来整个IMPLIMENT_DYNAMIC内容好像只是指定初值,其实不然,其关键在于使用了struct AFX_CLASSINIT,并调用了其构造函数,实现了linked list的连接工作(把classXXX加入到类型表中),定义如下:

struct AFX_CLASSINIT

{

    AFX_CLASSINIT(CRuntimeClass* pNewClass);//构造函数

}

AFX_CLASSINIT::AFX_CLASSINIT(CRuntimeClass* pNewClass)

{

    pNewClass->m_pNextClass = CRuntimeClass::pFirstClass;

    CRuntimeClass::pFirstClass = pNewClass;

}

 

 

例如:

//in header file

class CView: public CWnd

{

    DECLARE_DYNAMIC(CView)

    ...

};

//in implementation file

IMPLEMENT_DYNAMIC(CView,CWnd)


上述代码展开成为:

//in header file

class CView : public CWnd

{

public:

    static CRuntimeClass classCView;/

    virtual CRuntimeClass* GetRuntimeClass() const;

    ...

};

//in implementation file

static char _lpszCView[] = "CView";

CRuntimeClass CView::classCView = {

    _lpszCView,sizeof(CView),0xFFFF,NULL,&CWnd::classCWnd,NULL

    };

static AFX_CLASSINIT _init_CView(&CView::classCView);

CRuntimeClass *CView::GetRuntimeClass()const

{

    return &CView::classCView;

}

 

//程序中只需要简简单单的两个宏DECLARE_DYNAMIC(Cxxx)和IMPLEMENT_DYNAMIC(Cxxx,Cxxxbase),就完成了建构数据并加入链表的工作。



    使用这组宏的类必须要有基类,但是CObject没有基类怎么处理呢?

    链表的头,总是要特别费心处理,不能够套用一般的链表行为方式。我们的类根源CObject,不能套用现成的宏

其中DECLARE_NYNAMIC和IMPLEMENT_DYNAMIC,必须特别设计如下:

//in header file

class CObject

{

public:

    virtual CRuntimeClass* GetRuntimeClass()const;

    ...

public:

    static CRuntimeClass classObject;

};

//in implementation file

static char szCObject[] = "CObject";

struct CRuntimeClass CObject::classObject = {

    szCObject,sizeof(CObject),0xffff,NULL,NULL};

static AFX_CLASSINIT _init_CObject(&CObject::classCObject);

CRuntimeClass* CObject::GetRuntimeClass()const

{

    return &CObject::classCObject;

}

//做了一个让CObject的m_pBaseClass指向为空的操作,这样整个“类别型录”链表的头部就形成了。

 

 

在CObject中做以下实现就可以使用RTTI的IsKindOf功能了:

 

BOOL CObject::IsKindOf(const CRuntimeClass* pClass)const

{

   //simple SI case

   CRuntimeClass* pClassThis = GetRuntimeClass();

   return pClassThis->IsDerivedFrom(pClass);

}

BOOL CRuntimeClass::IsDerivedFrom(const CRuntimeClass* pBaseClass)const

{

   //Simple SI case

   const CRuntimeClass* pClassThis = this;

   while(pClassThis != NULL)

   {

     if(pClassThis == pBaseClass)

        return TRUE;

     pClassThis = pClassThis->m_pBaseClass;

   }

   return FALSE;

}

 

 

2.为了实现动态创建功能,增加了DECLARE_DYNCREATE/IMPLEMENT_DYNCREATE

#define DECLARE_DYNCREATE(class_name) "
    DECLARE_DYNAMIC(class_name) "
    static CObject* PASCAL CreateObject();

 

 

#define IMPLEMENT_DYNCREATE(class_name, base_class_name) /

CObject* PASCAL class_name::CreateObject() /

{ return new class_name; } /

IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, /

class_name::CreateObject, NULL)

 

//通过把CreateObject方法的指针保存到CRuntimeClass中,然后使用CRuntimeClass便可实现动态创建对象。

你可能感兴趣的:(struct,header,null,Class,mfc,pascal)