MFC中のマクロ

4720 ワード

MFCの実現を分析するには,まずMFCの多くのマクロから議論する.まず、前回お話ししたマクロを見てみましょう.
#define RUNTIME_CLASS(class_name) ((CRuntimeClass*)(&class_name::class##class_name))
というマクロの実装は簡単で、静的メンバー変数であるか、仮想関数であるかのいずれかのクラスのメンバー変数のアドレスを返すことです.ネーミングスペース文字で抽出するのは、この2つの場合にのみ使用できます.まず疑問を残して、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;
}
の から かるように、プログラム の1つのクラスが1つのCRuntimeClassに するため、ここでのデータは であり、あるクラスが のクラスのベースクラスである 、CRuntimeClassクラス を ることでポインタドメインpBaseClassが しくなる. のCreateObjectは、ユーザーが する を えます.