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は、ユーザーが する を えます.