MFC当中的宏

要分析MFC的实现首先要从MFC当中众多的宏开始讨论。首先看一个上次讲到的宏:

#define RUNTIME_CLASS(class_name) ((CRuntimeClass*)(&class_name::class##class_name))
这个宏的实现很简单,就是返回一个类当中的一个成员变量的地址,这个成员变量要么是静态成员变量,要么是虚拟函数。因为用命名空间符提取只能用于这两种情况。先留下疑问,看看CRuntimeClass的定义。
   struct CRuntimeClass
   {
   	LPCSTR m_lpszClassName;             //存放类的名称
   	int m_nObjectSize;                  //类的尺寸大小
   	UINT m_wSchema;                     // 一个标志符号
   	CObject* (PASCAL* m_pfnCreateObject)(); //如果这个函数为空,则表明类是一个虚拟类,不能有实例
   	CRuntimeClass* m_pBaseClass;            //基类的CRuntimeClass
   	CObject* CreateObject();                //创建
   	BOOL IsDerivedFrom(const CRuntimeClass* pBaseClass) const;//判断两个类别是否具有继承关系
   	void Store(CArchive& ar) const;                           //用于存放类别信息
   	static CRuntimeClass* PASCAL Load(CArchive& ar, UINT* pwSchemaNum);//用于加载类别信息
   	CRuntimeClass* m_pNextClass;       // 将整个CRuntimeClass类别链成一个链表
   };
***************************************************************
/*下面这个宏展开之后,定义了一个与类名息息相关的静态CRuntimeClass成员变量,另外定义了一个虚拟函数用于获取相应类的CRuntimeClass*/
   #define DECLARE_DYNAMIC(class_name) \
   public: \
   	static const AFX_DATA CRuntimeClass class##class_name; \
	virtual CRuntimeClass* GetRuntimeClass() const; \
*********************************************************************
/*用于对CRuntimeClass结构体进行填充,由于后面的成员函数并不是指针类型的,所以不需要填充。同时实现上面的GetRuntimeClass函数*/

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

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

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

RUNTIME_CLASS(base_class_name), NULL }; \

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)

通过上面的分析,不难看出,每个类都有一个类似于管家的结构体,这个结构体包含自身的信息,并且这个信息在整个程序当中是唯一的,同时这个结构体包含基类的的RuntimeClass的指针。

   #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)

这个宏的实现相对于之前的更进一步了,定义一个静态的成员函数,这个函数的实现是生成一个类别,而这个类别有CObject*指向,很很明显class_name是CObejct的子类别。并且在实现当中将静态成员函数传递到CRuntimeClass结构体当中,这样的话,CRuntimeClass类别就具有生成class_name类别的所有信息了。

   #define DECLARE_SERIAL(class_name) \
   	_DECLARE_DYNCREATE(class_name) \
   	AFX_API friend CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb);
******************************************************************************************
   #define IMPLEMENT_SERIAL(class_name, base_class_name, wSchema) \
   	CObject* PASCAL class_name::CreateObject() \
   		{ return new class_name; } \
   	_IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, \
   		class_name::CreateObject) \
   	AFX_CLASSINIT _init_##class_name(RUNTIME_CLASS(class_name)); \
   	CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb) \

{ pOb = (class_name*) ar.ReadObject(RUNTIME_CLASS(class_name)); \

return ar; } \


这个宏的实现实际上是用于在整个类的文档化,既将整个类的信息保存到文件当中,然后从文件中读出来,并进行相应的初始化。

上面的CRuntimeClass将所有的从CObject类继承来的类别连接一个链表,这样就可以在父类和子类之间传递消息,直到消息被其中某一个类处理或者所有的类都不处理,那么就到了默认的处理函数,也就是DefWindowProc。

BOOL CRuntimeClass::IsDerivedFrom(const CRuntimeClass* pBaseClass) const
{
 	const CRuntimeClass* pClassThis = this;
   	while (pClassThis != NULL)
   	{
   		if (pClassThis == pBaseClass)
   			return TRUE;
   		pClassThis = pClassThis->m_pBaseClass;
   	}
   	return FALSE;
}
CObject* CRuntimeClass::CreateObject()
{
   	if (m_pfnCreateObject == NULL)
   	{
   		return NULL;
   	}
   	CObject* pObject = NULL;
   	TRY
   	{
   		pObject = (*m_pfnCreateObject)();
   	}
   	END_TRY
   	return pObject;
}
从上面的实实现可以看出,由于整个程序当中一个类对应一个CRuntimeClass,所以这里的数据是唯一的,如果某一个类是另外一个类的基类,那么通过回溯整个CRuntimeClass类总会有一个指针域pBaseClass相等。而下面的CreateObject则给了一个用户处理的机会。

你可能感兴趣的:(C++,mfc)