一、先说说背景
最近做的一个项目中(MFC相关),有关窗口类继承自CCmdTarget类。而CCmdTarget类继承自CObject类。在这些类的定义与实现中,都有如下几个宏定义
DECLARE_DYNAMIC,IMPLEMENT_DYNAMIC,
DECLARE_DYNCREATE,IMPLEMENT_DYNCREATE
DECLARE_SERIAL,IMPLEMENT_SERIAL
二、扒一扒背后的故事
看了下微软的官方文档,继承CObject类是为了支持运行时类信息、动态创建和序列化。上面提到的几个宏,分别有如下作用
宏 | CObject::IsKindOf | CRuntimeClass::CreateObject | CArchive::operator>> CArchive::operator<< |
使用CObject基本功能 | 否 | 否 | 否 |
DECLARE_DYNAMIC | 是 | 否 | 否 |
DECLARE_DYNCREATE | 是 | 是 | 否 |
DECLARE_SERIAL | 是 | 是 | 是 |
1、使用CObject基本功能
无需多言
2、DECLARE_DYNAMIC(添加运行时类信息)
先看如何使用
//person.h
class CPerson : public CObject
{
DECLARE_DYNAMIC( CPerson )
// other declarations
};
//person.cpp
IMPLEMENT_DYNAMIC( CPerson, CObject )
//afx.h
#define DECLARE_DYNAMIC(class_name) \
protected: \
static CRuntimeClass* PASCAL _GetBaseClass(); \
public: \
static const CRuntimeClass class##class_name; \
static CRuntimeClass* PASCAL GetThisClass(); \
virtual CRuntimeClass* GetRuntimeClass() const; \
这里,我们发现了CRuntimeClass这个东西,那就暂时切换思路,看下CRuntimeClass是什么东东。通过宏定义,每个派生类中每个都有CRuntimeClass结构体静态成员变量及返回值为CRuntimeClass* 的函数。通过这些,就可以在运行时获取有关派生类对象或者基类CObject的信息。
//afx.h
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
#ifdef _AFXDLL
CRuntimeClass* (PASCAL* m_pfnGetBaseClass)();
#else
CRuntimeClass* m_pBaseClass;
#endif
// Operations
CObject* CreateObject();
BOOL IsDerivedFrom(const CRuntimeClass* pBaseClass) const;
// dynamic name lookup and creation
static CRuntimeClass* PASCAL FromName(LPCSTR lpszClassName);
static CRuntimeClass* PASCAL FromName(LPCWSTR lpszClassName);
static CObject* PASCAL CreateObject(LPCSTR lpszClassName);
static CObject* PASCAL CreateObject(LPCWSTR lpszClassName);
// Implementation
void Store(CArchive& ar) const;
static CRuntimeClass* PASCAL Load(CArchive& ar, UINT* pwSchemaNum);
// CRuntimeClass objects linked together in simple list
CRuntimeClass* m_pNextClass; // linked list of registered classes
const AFX_CLASSINIT* m_pClassInit;
};