15.5 提供运行期类型信息

提供运行期类型信息

和大多数编程框架一样,wxWidgets提供了比标准C++更多的运行期类型信息.这对于在运行期依对象类型决定行为,或者在上节提到的错误报告中都是很有用处的.并且它还允许你通过对象名来创建一个那种类型的变量.需要注意的是:只有派生自wxObject的类才可以使用wxWidgets的RTTI (运行期类型信息).

如果你不需要动态创建功能,你需要在类声明中使用DECLARECLASS(class)宏,而在类实现中使用 IMPLEMENT_CLASS(class, baseClass)宏,反之,则需要使用DECLARE_DYNAMIC_CLASS(class)宏和IMPLEMENT_DYNAMIC CLASS(class, baseClass)宏.另外,如果你希望使用动态创建功能,你还需要保证你的类拥有一个默认的构造函数,否则在编译那些用来动态产生某个对象的代码时, 编译器可能会报错.

下面是定义和动态创建一个对象的例子:

class MyRecord: public wxObject
{
DECLARE_DYNAMIC_CLASS(MyRecord)
public:
    MyRecord() {}
    MyRecord(const wxString& name) { m_name = name; }
    void SetName(const wxString& name) { m_name = name; }
    const wxString& GetName() const { return m_name; }
private:
    wxString m_name;
};
IMPLEMENT_DYNAMIC_CLASS(MyRecord, wxObject)
MyRecord* CreateMyRecord(const wxString& name)
{
    MyRecord* rec = wxDynamicCast(wxCreateDynamicObject(wxT("MyRecord")), MyRecord);
    if (rec)
        rec->SetName(name);
    return rec;
}

当CreateMyRecord被调用的时候,wxCreateDynamicObject负责创建所需的对象,而 wxDynamicCast则负责进行类型检查,如果检查失败则返回NULL.也许你觉得这个代码看上去并没有什么实际的用处,但是在从文件加载一堆不同类型的对象的时候,这是非常有用的.对象的数据和它的名称被一起存放在文件中,通过名字创建一个对象的实例,然后再使用这个实例加载相应的数据.

下面我们来介绍以下运行期类型信息的一起其它相关宏:

CLASSINFO(class)返回一个指向wxClassInfo类型的指针.你可以使用wxObject::IsKindOf函数来判断某个对象是否是对应的类型:

if (obj->IsKindOf(CLASSINFO(MyRecord)))
{
    ...
}

使用DECLARE_ABSTRACT_CLASS(class)和IMPLEMENT_ABSTRACT_CLASS(class, baseClass)来定义虚类.

使用DECLARE_CLASS2(class)和IMPLEMENT_CLASS2(class, baseClass1, baseClass2)来定义有两个父类的类.

使用DECLARE_APP(class)和IMPLEMENT_APP(class)来使得wxWidgets知道整个应用程序类的运行期类型信息.

wxConstCast(ptr, class)用来代替const_cast<class *>(ptr),如果编译器不支持const_cast,则使用旧的C语言的类型强制转换.

wxDynamicCastThis(class)相当于wxDynamicCast(this, class), 但是后者在某些编译器上会导致永真比较告警,因为它将测试是否指针为空,而this指针永远不可能为空,前者可以避免这个告警.

wxStaticCast(ptr, class)在调试模式将检查强制类型转换的有效性(如果wxDynamicCast(ptr, class) == NULL将引发断言错误)然后返回static_cast<class*>(ptr)的等同结果.

wx_const_cast(T, x)在编译器支持的情况下等同于const_cast<T>(x),否则等同于(T)x(C语言类型强制转换语法).和 wxConstCast不同的是,它强制转换的是T本身而不是指向T的指针,而且参数的顺序也和标准强制转换的顺序相同.

wx_reinterpret_cast(T, x)则相当于reinterpret_cast<T>(x),如果编译器不支持则等同于(T)x.

wx_static_cast(T, x)等同于static_cast<T>(x),如果编译器不支持则等同于(T)x. 和wxStaticCast不同的是,它不做类型检查,并且采用和标准的静态转换相同的参数顺序,而且转换的也是T而不是指向T的指针.