wxWidgets和MFC动态类型信息比较
来源:互联网 发布:手机五级网络 编辑:程序博客网 时间:2024/05/23 00:27
快乐虾
http://blog.csdn.net/lights_joy/
lights@hb165.com
本文适用于
wxWidgets-
vs2005
欢迎转载,但请保留作者信息
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;
让人不由自主想起了CObject和CRuntimeClass:
class AFX_NOVTABLE CObject
{
public:
virtual CRuntimeClass* GetRuntimeClass() const;
…………………..
public:
BOOL IsKindOf(const CRuntimeClass* pClass) const;
………………………………….
public:
static const CRuntimeClass classCObject;
……………………………
};
可以认为它们都是同样的想法,都是用一个类来保存类型信息,只不过MFC使用的类(实际声明为struct)叫作CRuntimeClass而wxWidgets把它叫做wxClassInfo而已。
1.1 储存的类型信息
同样地比较CRuntimeClass和wxClassInfo,可以发现它们储存的类型信息也是几乎一致的:
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_baseInfo1和m_baseInfo2,而CRuntimeClass则只有一个m_pBaseClass,莫非是wxWidgets用m_baseInfo2来支持多重继承?暂时不是很了解。
5. CRuntimeClass用m_pClassInit和m_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则是将所有的类信息都放在了哈希表中。
至于其它的一些操作如判断子类和父类的关系等等则几乎是一样的,在此不做分析。
参考资料
打造windows下的嵌入式开发工具(6):wxWidgets-2.8.8(
用dll方式编译wxWidgets-2.8.8(
- wxWidgets和MFC动态类型信息比较
- MFC与wxWidgets比较
- MFC与wxWidgets比较
- MFC与wxWidgets比较(2)
- GTK+, QT,wxWidgets, MFC的比较
- 理解“MFC的动态类型识别和动态创建”
- Windows Forms、MFC、WTL、WxWidgets、Qt、GTK综合比较
- C++ 动态类型比较
- [wxWidgets]XRC和动态子菜单
- 第十四章 类型信息 反射 动态代理 空对象 接口和类型信息
- MFC复习和学习 第四章 MFC切分窗口 MFC运行时类信息 MFC动态创建
- 仿MFC动态类型识别
- MFC 动态类型识别思路
- QT和MFC比较
- .net 和MFC 比较
- Qt和MFC比较
- GLUT和wxWidgets在OpenGL开发中的比较
- GTK+,wxWidgets,QT比较
- 创建虚拟目录
- c语言常见问题-声明和初始化
- 我开张了,欢迎您的到来。
- 身心保健的100条谚语
- 计算机考证
- wxWidgets和MFC动态类型信息比较
- 一个简单的折叠效果
- 调整数组顺序使奇数位于偶数前面
- 中国人应该知道的知识
- python整理九——浅谈浅拷贝与深拷贝
- Linux Telnet SSH
- 真是老古董,原来书是可以这样买的
- sql server 2005 还是错了
- 一位大四学生的面试经历和体会