深入浅出MFC第2版(PDF格式)-第34部分
按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
第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
{
return &CObject::classCObject;
}
并且,CRuntimeClass 中的static 成员变量应该要初始化(如果你忘记了,赶快复习第
2章的「静态成员(变量与函数)」一节):
// in implementation file
CRuntimeClass* CRuntimeClass::pFirstClass = NULL;
终于,整个「类别型录」串行的头部就这样形成了:
CObject::classCObject
“CObject”
sizeof(CObject)
CRuntimeClass::pFirstClass 0xFFFF
(static
变量) m_pfnCreateObject NULL
m_pBaseClass NULL
m_pNextClass
NULL
128
…………………………………………………………Page 191……………………………………………………………
第3章 MFC 六大關鍵技術之模擬
范例程序Frame3 在。h 档中有这些类别声明:
CObject
CObject
CCmdTarget
CCmdTarget
CWinThread
CWinThread
CWinApp
CWinApp
CMyWinApp
CMyWinApp
CWnd
CWnd
CView
CMyView
CMyView
CFrameWnd
CFrameWnd
CMyFrameWnd
CMyFrameWnd
CDocument
CDocument
CMyDoc
CMyDoc
class CObject
{
。。。
};
class CCmdTarget : public CObject
{
DECLARE_DYNAMIC(CCmdTarget)
。。。
};
class CWinThread : public CCmdTarget
{
DECLARE_DYNAMIC(CWinThread)
。。。
};
class CWinApp : public CWinThread
{
DECLARE_DYNAMIC(CWinApp)
。。。
};
class CDocument : public CCmdTarget
{
DECLARE_DYNAMIC(CDocument)
129
…………………………………………………………Page 192……………………………………………………………
第篇 勿在浮砂築高台
。。。
};
class CWnd : public CCmdTarget
{
DECLARE_DYNAMIC(CWnd)
// 其实在MFC 中是DECLARE_DYNCREATE(),见下节。
。。。
};
class CFrameWnd : public CWnd
{
// 其实在MFC 中是DECLARE_DYNCREATE(),见下节。
DECLARE_DYNAMIC(CFrameWnd)
。。。
};
class CView : public CWnd
{
DECLARE_DYNAMIC(CView)
。。。
};
class CMyWinApp : public CWinApp
{
。。。
};
class CMyFrameWnd : public CFrameWnd
{
。。。 // 其实在MFC 应用程序中这里也有DECLARE_DYNCREATE(),见下节。
};
class CMyDoc : public CDocument
{
。。。 // 其实在MFC 应用程序中这里也有DECLARE_DYNCREATE(),见下节。
};
class CMyView : public CView
{
。。。 // 其实在MFC 应用程序中这里也有DECLARE_DYNCREATE(),见下节。