网站公告列表

  没有公告

加入收藏
设为首页
联系本站
您现在的位置: AnalogCN安诺电子 >> 文章 >> 技术交流 >> 文章正文
  wxWidgets和MFC动态类型信息比较           ★★★ 【字体:
wxWidgets和MFC动态类型信息比较
作者:快乐虾    文章来源:http://blog.csdn.net/lights_joy    点击数:    更新时间:2008-9-8    

wxWidgets被设计为支持动态类型信息。这个支持由wxObject实现,看看:

class WXDLLIMPEXP_BASE wxObject

{

    DECLARE_ABSTRACT_CLASS(wxObject)

……………….

public:

    bool IsKindOf(wxClassInfo *info) const;

………………

};

在这里DECLARE_ABSTRACT_CLASS定义为:

#define DECLARE_ABSTRACT_CLASS(name)                                          \

    public:                                                                   \

        static wxClassInfo ms_classInfo;                                      \

        virtual wxClassInfo *GetClassInfo() const;

让人不由自主想起了CObjectCRuntimeClass

class AFX_NOVTABLE CObject

{

public:

     virtual CRuntimeClass* GetRuntimeClass() const;

…………………..

public:

     BOOL IsKindOf(const CRuntimeClass* pClass) const;

………………………………….

public:

     static const CRuntimeClass classCObject;

……………………………

};

可以认为它们都是同样的想法,都是用一个类来保存类型信息,只不过MFC使用的类(实际声明为struct)叫作CRuntimeClasswxWidgets把它叫做wxClassInfo而已。

1.1    储存的类型信息

同样地比较CRuntimeClasswxClassInfo,可以发现它们储存的类型信息也是几乎一致的:

class WXDLLIMPEXP_BASE wxClassInfo

{

public:

    wxClassInfo( const wxChar *className,

                 const wxClassInfo *baseInfo1,

                 const wxClassInfo *baseInfo2,

                 int size,

                 wxObjectConstructorFn ctor )

        : m_className(className)

        , m_objectSize(size)

        , m_objectConstructor(ctor)

        , m_baseInfo1(baseInfo1)

        , m_baseInfo2(baseInfo2)

        , m_next(sm_first)

        {

            sm_first = this;

            Register();

        }

………………………….

public:

    const wxChar            *m_className;

    int                      m_objectSize;

    wxObjectConstructorFn    m_objectConstructor;

    const wxClassInfo       *m_baseInfo1;

    const wxClassInfo       *m_baseInfo2;

    static wxClassInfo      *sm_first;

    wxClassInfo             *m_next;

    static wxHashTable      *sm_classTable;

……………………..

};

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;

…………………………

 

     // CRuntimeClass objects linked together in simple list

     CRuntimeClass* m_pNextClass;       // linked list of registered classes

     const AFX_CLASSINIT* m_pClassInit;

};

从上面列出的两个类可以发现几个不同:

1.              wxClassInfo通过类的构造函数来给wxObject::ms_classInfo这个静态变量赋值,而CRuntimeClass则通过结构体的赋值来构建CObject::classCObject

2.              wxWidgets中,每个类用来储存类型信息的静态变量名称都是一致的,都叫ms_classInfo,而MFC中,每个类储存类型信息的静态变量名称则是不一致的,如CObject中储存类型信息的变量名称为classCObject,而CcmdTarget中储存类型信息的变量名称则为classCCmdTarget

3.              CRuntimeClass中多了一个叫m_wSchema的整数变量,因为MFC被设计为支持序列化。

4.              wxClassInfo中用于指向基类的指针有两个m_baseInfo1m_baseInfo2,而CRuntimeClass则只有一个m_pBaseClass,莫非是wxWidgetsm_baseInfo2来支持多重继承?暂时不是很了解。

5.              CRuntimeClassm_pClassInitm_pfnCreateObject来支持动态创建,wxClassInfo则只使用了m_objectConstructor这个回调函数。

6.              wxClassInfo中多了一个指向类型信息链表头的指针sm_first

7.              wxClassInfo中多了个sm_classTable,从名字猜测似乎是wxWidgets使用哈希表来进行类的快速查找。

1.2    声明支持动态类型

MFC中,如果一个类想要支持动态类型信息,它必须在类的定义中加上DECLARE_DYNAMIC,相应地在类的实现文件中使用IMPLEMENT_DYNAMIC

DECLARE_DYNAMIC的定义为:

#define DECLARE_DYNAMIC(class_name) \

public: \

     static const CRuntimeClass class##class_name; \

     virtual CRuntimeClass* GetRuntimeClass() const; \

IMPLEMENT_DYNAMIC则定义为:

#define IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew, class_init) \

     AFX_COMDAT const CRuntimeClass class_name::class##class_name = { \

         #class_name, sizeof(class class_name), wSchema, pfnNew, \

              RUNTIME_CLASS(base_class_name), NULL, class_init }; \

     CRuntimeClass* class_name::GetRuntimeClass() const \

         { return RUNTIME_CLASS(class_name); } \

 

#define IMPLEMENT_DYNAMIC(class_name, base_class_name) \

     IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, NULL, NULL)

就这样,子类保存了父类中表示类型信息的CRuntimeClass指针。

wxWidgets中,在类的声明中使用DECLARE_ABSTRACT_CLASS或者其它在此基础上扩展出来的宏来声明支持动态类型信息。

#define DECLARE_ABSTRACT_CLASS(name)                                          \

    public:                                                                   \

        static wxClassInfo ms_classInfo;                                      \

        virtual wxClassInfo *GetClassInfo() const;

然后使用wxIMPLEMENT_CLASS_COMMON或者在其基础上扩展的宏来给ms_classInfo赋值。

#define wxIMPLEMENT_CLASS_COMMON(name, basename, baseclsinfo2, func)          \

    wxClassInfo name::ms_classInfo(wxT(#name),                                \

            &basename::ms_classInfo,                                          \

            baseclsinfo2,                                                     \

            (int) sizeof(name),                                               \

            (wxObjectConstructorFn) func);                                    \

                                                                              \

    wxClassInfo *name::GetClassInfo() const                                   \

        { return &name::ms_classInfo; }

由于在wxWidgets中是使用了wxClassInfo的构造函数来完成一些变量的赋值,而在此构造函数中调用了Register函数,下面再看看wxClassInfo::Register

// This function wasn't written to be reentrant but there is a possiblity of

// reentrance if something it does causes a shared lib to load and register

// classes. On Solaris this happens when the wxHashTable is newed, so the first

// part of the function has been modified to handle it, and a wxASSERT checks

// against reentrance in the remainder of the function.

 

void wxClassInfo::Register()

{

    if ( !sm_classTable )

    {

        wxHashTable *classTable = new wxHashTable(wxKEY_STRING);

 

        // check for reentrance

        if ( sm_classTable )

            delete classTable;

        else

            sm_classTable = classTable;

    }

 

    // Using IMPLEMENT_DYNAMIC_CLASS() macro twice (which may happen if you

    // link any object module twice mistakenly, or link twice against wx shared

    // library) will break this function because it will enter an infinite loop

    // and eventually die with "out of memory" - as this is quite hard to

    // detect if you're unaware of this, try to do some checks here.

    wxASSERT_MSG( sm_classTable->Get(m_className) == NULL,

        wxString::Format

        (

            _T("Class \"%s\" already in RTTI table - have you used IMPLEMENT_DYNAMIC_CLASS() multiple times or linked some object file twice)?"),

            m_className

        )

    );

 

    sm_classTable->Put(m_className, (wxObject *)this);

 

}

从这个函数可以看出,wxWidgets使用了一个哈希表来完成类名称和wxClassInfo指针之间的映射关系,这点是和MFC不同的,MFC仅仅是将需要动态创建的类的类型信息用单链表链接在一起,而wxWidgets则是将所有的类信息都放在了哈希表中。

至于其它的一些操作如判断子类和父类的关系等等则几乎是一样的,在此不做分析。

文章录入:admin    责任编辑:admin 
  • 上一篇文章:

  • 下一篇文章:
  • 发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
    最新热点 最新推荐 相关文章
    前置放大器在移动医疗服务系
    便携式多通道大容量生理信号
    防腐监测仪的设计与应用
    基于AD1674的酶标仪的设计
    基于C/S模式的JRTPLIB库的测
    ffmpeg与jrtplib相结合应用
    blackfin模拟摄像头驱动中的
    可编程逻辑在数字信号处理系
    发现VDSP4.5一个BUG:单步调
    VDSP5.0双核工程下sml3中的变
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    版权所有:AnalogCN安诺电子 湘ICP备06016315号