按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
m_wSchema
CRuntimeClass::pFirstClass m_pfnCreateObject
(static 变量)
m_pBaseClass
m_pNextClass
我希望,每一个类别都能拥有这样一个CRuntimeClass 成员变量,并且最好有一定的命名
规则(例如在类别名称之前冠以〃class〃 作为它的名称),然后,经由某种手段将整个
类别库构造好之后,「类别型录」能呈现类似这样的风貌:
CObject::classCObject CCmdTarget::classCCmdTarget CWinThread::classCWinThread
“CObject” “CCmdTarget” “CWinThread”
m_pBaseClass m_pBaseClass m_pBaseClass
m_pNextClass m_pNextClass m_pNextClass
NULL NULL CObject::classCObject CCmdTarget::classCCmdTarget
CWnd::classCWnd CWinApp::classCWinApp
“CWnd” “CWinApp”
static 变量
CRuntimeClass::pFirstClass
m_pBaseClass m_pBaseClass
m_pNextClass m_pNextClass
CCmdTarget::classCCmdTarget CWinThread::classCWinThread
124
…………………………………………………………Page 187……………………………………………………………
第3章 MFC 六大關鍵技術之模擬
DECLARE_DYNAMIC / IMPLEMENT_DYNAMIC 宏
为了神不知鬼不觉把CRuntimeClass 对象塞到类别之中,并声明一个可以抓到该对象地
址的函数,我们定义DECLARE_DYNAMIC 宏如下:
#define DECLARE_DYNAMIC (class_name)
public:
static CRuntimeClass class##class_name;
virtual CRuntimeClass* GetRuntimeClass() const;
出现在宏定义之中的## ,用来告诉编译器,把两个字符串系在一起。如果你这么使用此
宏:
DECLARE_DYNAMIC(CView)
编译器前置处理器为你做出的码是:
public:
static CRuntimeClass classCView;
virtual CRuntimeClass* GetRuntimeClass() const;
这下子,只要在声明类别时放入DECLARE_DYNAMIC 宏即万事OK 喽。
不,还没有OK ,类别型录(也就是各个CRuntimeClass 对象)的内容指定以及串接工
作最好也能够神不知鬼不觉,我们于是再定义IMPLEMENT_DYNAMIC 宏:
#define IMPLEMENT_DYNAMIC (class_name; base_class_name)
_IMPLEMENT_RUNTIMECLASS(class_name; base_class_name; 0xFFFF; NULL)
其中的_IMPLEMENT_RUNTIMECLASS 又是一个宏。这样区分是为了此一宏在「动
态生成」(下一节主题)时还会用到。
#define _IMPLEMENT_RUNTIMECLASS (class_name; base_class_name;wSchema;pfnNew)
static char _lpsz##class_name'' = #class_name;
CRuntimeClass class_name::class##class_name = {
_lpsz##class_name; sizeof(class_name); wSchema; pfnNew;
RUNTIME_CLASS (base_class_name); NULL };
static AFX_CLASSINIT _init_##class_name(&class_name::class##class_name);
CRuntimeClass* class_name::GetRuntimeClass() const
{ return &class_name::class##class_name; }
125
…………………………………………………………Page 188……………………………………………………………
第篇 勿在浮砂築高台
其中又有RUNTIME_CLASS 宏,定义如下:
#define RUNTIME_CLASS (class_name)
(&class_name::class##class_name)
看起来整个IMPLEMENT_DYNAMIC 内容好象只是指定初值,不然,其曼妙处在于它所
使用的一个struct AFX_CLASSINIT ,定义如下:
struct AFX_CLASSINIT
{ AFX_CLASSINIT(CRuntimeClass* pNewClass); };
这表示它有一个构造式(别惊讶,C++ 的struct 与class 都有构造式),定义如下:
AFX_CLASSINIT::AFX_CLASSINIT (CRuntimeClass* pNewClass)
{
pNewClass…》m_pNextClass = CRuntimeClass::pFirstClass;
CRuntimeClass::pFirstClass = pNewClass;
}
很明显,此构造式负责linked list 的串接工作。
整组宏看起来有点吓人,其实也没有什么,文字代换而已。现在看看这个实例:
// in header file
class CView : public CWnd
{
DECLARE_DYNAMIC(CView)
。。。
};
// in implementation file
IMPLEMENT_DYNAMIC(CView; CWnd)
上述的码展开来成为:
// in header file
class CView : public CWnd
{
public:
static CRuntimeClass classCView;
virtual CRuntimeClass* GetRuntimeClass() const;
。。。
};
126
…………………………………………………………Page 189……………………………………………………………
// in implementation file
static char _lpszCView'' = 〃CView〃;
CRuntimeClass CView::classCView = {
_lpszCView; sizeof(CView); 0xFFFF; NULL;
&CWnd::classCWnd; NULL };
static AFX_CLASSINIT _init_CView (&CView::classCView);
CRuntimeClass* CView::GetRuntimeClass() const
{ return &CView::classCView; }
于是乎, 程序中只需要简简单单的两个宏DECLARE_DYNAMIC(Cxxx) 和
IMPLEMENT_DYNAMIC(Cxxx; Cxxxbase) ,就完成了构造资料并加入串行的工作:
Cxxx ::classCxxx
“Cxxx”
sizeof(Cxxx)
0xFFFF
m_pfnCreateObject NULL
m_pBaseClass Cxxxbase::classCxxxbase
m_pNextClass
可是你知道,串行的头,总是需要特别费心处理,不能够套用一般的串行行为模式。我
们的类别根源CObject , 不能套用现成的宏DECLARE_DYNAMIC 和
IMPLEMENT_DYNAMIC ,必须特别设计如下:
// in header file
class CObject
{
public:
virtual CRuntimeClass* GetRuntimeClass() const;
。。。
public:
static CRuntimeClass classCObject;
};
127
…………………………………………………………Page 190……………………………………………………………
第篇 勿在浮砂築高台
// in implementation file
static char szCObject'' = 〃CObject〃;
struct CRuntimeClass CObject::classCObject =
{ szCObject; sizeof(CObject); 0xffff; NULL; NULL };
static AFX_CLASSINIT _init_CObject (&CObject::classCObject);
CRuntimeClass* CObject::GetRuntimeClass() const
{