[Effective WX] wx中的反射机制:DANYMIC_CLASS的实现

本文介绍了wx编程中利用DECLARE_DYNAMIC_CLASS和IMPLEMENT_DYNAMIC_CLASS宏实现的反射机制。这两个宏帮助类存储wxClassInfo静态变量,并提供类信息访问接口。DECLARE_DYNAMIC_CLASS用于非抽象类,而DECLARE_ABSTRACT_CLASS用于抽象类。IMPLEMENT_DYNAMIC_CLASS宏负责初始化类的wxClassInfo,注册到类表中,以便通过类名查找并进行对象创建和类型检查。wxClassInfo类通过构造函数将类信息注册到哈希表,wxIS_KIND_OF和wxIsKindOf宏则用于判断对象的类继承关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

wx利用两个宏实现了几乎所有以wx开头的窗口类的反射机制:
DECLARE_DYNAMIC_CLASS
IMPLEMENT_DYNAMIC_CLASS

当一个类想借助于wx实现的dynamic_class的机制,必须得继承于wxObject或者是它的子类。有了这个前提条件之后,在你的类中,你只需要这样操作:
1. 在类的声明中,写下:
DECLARE_DYNAMIC_CLASS($your_class_name);

2. 在类的实现文件中,写下:
IMPLEMENT_DYNAMIC_CLASS($your_class_name, $base_class_from_wxObject);

那么这2个宏到底帮我们做了些什么事情呢,我们来展开那2个宏来看看:
首先是 DECLARE_DYNAMIC_CLASS($your_class_name)
#define DECLARE_ABSTRACT_CLASS (name)                                          \
    public:                                                                   \
        static wxClassInfo ms_classInfo;                                      \
        virtual wxClassInfo *GetClassInfo() const;

#define DECLARE_DYNAMIC_CLASS (name)                                           \
    DECLARE_ABSTRACT_CLASS(name )                                              \
    static wxObject * wxCreateObject();

如果你的类不是抽象类,请用 DECLARE_DYNAMIC_CLASS,否则就用 DECLARE_ABSTRACT_CLASS。区别在于抽象类是无法实例化的,也就没办法提供对象构造器。我们具体来看下 DECLARE_ABSTRACT_CLASS这个宏。
这个宏主要是帮助提供了一个类wxClassInfo的静态变量,用来存储这个类的信息,同时也提供了访问给外界这个静态变量的接口。
所以总体来说,DECLEAR_*宏是在我们类中添加了额外的用来存储类相关信息的一个静态变量。有了这个静态变量,外界就可以通过Get接口来获取它的相关信息。
下面来看看 IMPLEMENT_DYNAMIC_CLASS宏。
#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; }

#define wxIMPLEMENT_CLASS_COMMON1 (name, basename, func)                       \
    wxIMPLEMENT_CLASS_COMMON(name , basename, NULL, func)

#define IMPLEMENT_DYNAMIC_CLASS (name, basename)                               \
    wxIMPLEMENT_CLASS_COMMON1(name , basename, name::wxCreateObject )           \
    wxObject* name ::wxCreateObject()                                          \
        { return new name; }

wx中最多只能让一个dynamic继承于2个wxObject子类,应该是虚继承。所以 wxIMPLEMENT_CLASS_COMMON只提供了2个basename接口。
从展开的宏来看,它主要做的事情就是初始化我们类的静态变量(ms_classInfo),初始化时,传入的动态对象构造器就是 wxCreateObject(简单的调用new操作符)。

所以下面我们来看下wxClassInfo类。
typedef wxObject *(*wxObjectConstructorFn)( void);

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();
        }

    static wxHashTable       *sm_classTable;
...
void wxClassInfo ::Register()
{
    if ( !sm_classTable )
    {
        wxHashTable *classTable = new wxHashTable(wxKEY_STRING );

        // check for reentrance
        if ( sm_classTable )
            delete classTable ;
        else
            sm_classTable = classTable ;
    }
    sm_classTable->Put (m_className, ( wxObject *)this );
}

这个类的构造函数仅仅是将类和它类名注册到一个hash table中,这个hash table是以类名为字符串作为key.

以上是C++中反射机制的比较典型的实现方式。

wx提供了下面2个宏操作:
#define wxIS_KIND_OF (obj, className) obj->IsKindOf (&className:: ms_classInfo)

// Just seems a bit nicer-looking (pretend it's not a macro)
#define wxIsKindOf (obj, className) obj->IsKindOf (&className:: ms_classInfo)

判断某个类的对象,是否属于某个class,这种属于应该是按照类的继承数来搜索的,满足"IS-A"关系。
有了wx那样实现机制,我们可以通过className可以很容器的查找到关存在它内部的classInfo变量。
IsKindOf函数定义在wxObject内部,要知道wxObject也是添加了DECLEAR*宏的:
DECLARE_ABSTRACT_CLASS  ( wxObject )
所以自然也有wxClassInfo信息。这个IsKindOf转调用wxClassInfo::IsKindOf。
bool wxObject ::IsKindOf( wxClassInfo *info ) const
{
    wxClassInfo *thisInfo = GetClassInfo();
    return (thisInfo ) ? thisInfo-> IsKindOf(info ) : false ;
}

     bool wxClassInfo::IsKindOf(const wxClassInfo *info ) const
    {
        return info != 0 &&
               ( info == this ||
                 ( m_baseInfo1 && m_baseInfo1 ->IsKindOf( info) ) ||
                 ( m_baseInfo2 && m_baseInfo2 ->IsKindOf( info) ) );
    }


所以它做的事情很简单,就是判断它们的wxClassInfo是否是同一个,或者如果该请求类有基类的话,基类是否那个条件。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值