友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
深入浅出MFC第2版(PDF格式)-第23部分
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 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(),见下节。
};
范例程序Frame3 在。cpp 档中有这些动作:
IMPLEMENT_DYNAMIC(CCmdTarget; CObject)
IMPLEMENT_DYNAMIC(CWinThread; CCmdTarget)
IMPLEMENT_DYNAMIC(CWinApp; CWinThread)
IMPLEMENT_DYNAMIC(CWnd; CCmdTarget) // 其实在MFC 中它是IMPLEMENT_DYNCREATE(),见下节。
IMPLEMENT_DYNAMIC(CFrameWnd; CWnd) // 其实在MFC 中它是IMPLEMENT_DYNCREATE(),见下节。
IMPLEMENT_DYNAMIC(CDocument; CCmdTarget)
IMPLEMENT_DYNAMIC(CView; CWnd)
于是组织出图3…1 这样一个大网。
130
…………………………………………………………Page 193……………………………………………………………
第3章 MFC 六大關鍵技術之模擬
CObject::classCObject CCmdTarget::classCCmdTarget CWinThread::classCWinThread
“CObject” “CCmdTarget” “CWinThread”
m_pBaseClass m_pBaseClass m_pBaseClass
m_pNextClass m_pNextClass m_pNextClass
NULL
NULL
CFrameWnd::classCFrameWnd CWnd::classCWnd CWinApp::classCWinApp
“CFrameWnd” “CWnd” “CWinApp”
m_pBaseClass m_pBaseClass m_pBaseClass
m_pNextClass m_pNextClass m_pNextClass
CDocument::classCDocument CView::classCView
“CDocument” “CView”
(static 变量)
CRuntimeClass::pFirstClass
m_pBaseClass m_pBaseClass
m_pNextClass m_pNextClass
图3…1 CRuntimeClass 对象构成的类别型录网。本图只列出与RTTI 有关系
的成员。
为了实证整个类别型录网的存在,我在main 函数中调用PrintAllClasses ,把串行中的每
一个元素的类别名称、对象大小、以及schema no。 印出来:
void PrintAllClasses()
{
CRuntimeClass* pClass;
// just walk through the simple list of registered classes
for (pClass = CRuntimeClass::pFirstClass; pClass != NULL;
pClass = pClass…》m_pNextClass)
{
cout m_lpszClassName
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!