深入浅出MFC第2版(PDF格式)-第38部分
按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
N U L L
C F r a m e W n d : : c l a s s C F r a m e W n d C W n d : : c l a s s C W n d C W i n A p p : : c l a s s C W i n A p p
“ C F r a m e W n d ” “ C W n d ” “ C W in A p p ”
m _ p B a s e C la s s m _ p B a s e C la s s m _ p B a s e C la s s
m _ p N e x t C la s s m _ p N e x t C la s s m _ p N e x t C la s s
C D o c u m e n t : : c l a s s C D o c u m e n t C V i e w : : c l a s s C V i e w
“ C D o c u m e n t ” “ C V ie w ”
(s t a t i c 变量)
C R u n t i m e C l a s s : : p F i r s t C l a s s
m _ p B a s e C la s s m _ p B a s e C la s s
m _ p N e x t C la s s m _ p N e x t C la s s
「对象生成器」CreateObject 函数很简单,只要说new 就好。
从宏的定义我们很清楚可以看出,拥有动态生成(Dynamic Creation )能力的类别库,
必然亦拥有执行时期类型识别(RTTI )能力,因为_DYNCREATE 宏涵盖了_DYNAMIC
宏。
注意:以下范例直接跳到Frame6 。本书第一版有一个Frame5 程序,用以仿真MFC 2。5
对动态生成的作法。往事已矣,读者曾经来函表示没有必要提过去的东西,徒增脑力负
荷。我想也是,况且MFC 4。x 的作法更好更容易了解,所以我把Frame5 拿掉了,但仍
保留着序号。
145
…………………………………………………………Page 208……………………………………………………………
第篇 勿在浮砂築高台
范例程序Frame6 在。h 档中有这些类别声明:
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)
。。。
};
class CWnd : public CCmdTarget
{
DECLARE_DYNCREATE(CWnd)
。。。
};
class CFrameWnd : public CWnd
{
DECLARE_DYNCREATE(CFrameWnd)
。。。
};
class CView : public CWnd
{
DECLARE_DYNAMIC(CView)
。。。
};
class CMyWinApp : public CWinApp
{
。。。
};
class CMyFrameWnd : public CFrameWnd
146
…………………………………………………………Page 209……………………………………………………………
第3章 MFC 六大關鍵技術之模擬
{
DECLARE_DYNCREATE(CMyFrameWnd)
。。。
};
class CMyDoc : public CDocument
{
DECLARE_DYNCREATE(CMyDoc)
。。。
};
class CMyView : public CView
{
DECLARE_DYNCREATE(CMyView)
。。。
};
在。cpp 档中又有这些动作:
IMPLEMENT_DYNAMIC(CCmdTarget; CObject)
IMPLEMENT_DYNAMIC(CWinThread; CCmdTarget)
IMPLEMENT_DYNAMIC(CWinApp; CWinThread)
IMPLEMENT_DYNCREATE(CWnd; CCmdTarget)
IMPLEMENT_DYNCREATE(CFrameWnd; CWnd)
IMPLEMENT_DYNAMIC(CDocument; CCmdTarget)
IMPLEMENT_DYNAMIC(CView; CWnd)
IMPLEMENT_DYNCREATE(CMyFrameWnd; CFrameWnd)
IMPLEMENT_DYNCREATE(CMyDoc; CDocument)
IMPLEMENT_DYNCREATE(CMyView; CView)
于是组织出图3…2 这样一个大网。
147
…………………………………………………………Page 210……………………………………………………………
第篇 勿在浮砂築高台
CObject::classCObject CCmdTarget::classCCmdTarget CWinThread::classCWinThread
“CObject” “CCmdTarget” “CWinThread”
4 4 4
m_pfnCreateObject NULL m_pfnCreateObject NULL m_pfnCreateObject NULL
m_pNextClass m_pNextClass m_pNextClass
NULL
CFrameWnd::classCFrameWnd CWnd::classCWnd CWinApp::classCWinApp
“CFrameWnd” “CWnd” “CWinApp”
12 4 4
m_pfnCreateObject m_pfnCreateObject m_pfnCreateObject NULL
m_pNextClass m_pNextClass m_pNextClass
CDocument::classCDocument CView::classCView
“CDocument” “CView” (static 变量)
4 4 CRuntimeClass::pFirstClass
m_pfnCreateObject NULL m_pfnCreateObject NULL
m_pNextClass m_pNextClass
图3…2 以CRuntimeClass 对象构成的 「类别型录网」。本图只列出与动态
生成 (Dynamic Creation)有关系的成员。凡是m_pfnCreateObject
不为NULL 者, 即可动态生成。
现在,我们开始仿真动态生成。首先在main 函数中加上这一段码:
void main()
{
。。。
//Test Dynamic Creation
CRuntimeClass* pClassRef;
CObject* pOb;
while(1)
{
148
…………………………………………………………Page 211……………………………………………………………
第3章 MFC 六大關鍵技術之模擬
if ((pClassRef = CRuntimeClass::Load()) == NULL)
break;
pOb = pClassRef…》CreateObject();
if (pOb != NULL)
pOb…》SayHello();
}
}
并设计
CRuntimeClass CreateObj ect CRuntimeClass Load
:: 和 :: 如:
// in implementation file
CObject* CRuntimeClass::CreateObject()
{
if (m_pfnCreateObject == NULL)
{
TRACE1(〃Error: Trying to create object which is not 〃
〃DECLARE_DYNCREATE nor DECLARE_SERIAL: %hs。n〃;
m_lpszClassName);
return NULL;
}
CObject* pObject = NULL;
pObject = (*m_pfnCreateObject)();
return pObject;
}
CRuntimeClass* PASCAL CRuntimeClass::Load()
{
char szClassName'64';
CRuntimeClass* pClass;
// JJHOU : instead of Load from file; we Load from cin。
cout 》 szClassName;
for (pClass = pFirstClass; pClass != NULL; pClass = pClass…》m_pNextClass)
{
if (strcmp(szClassName; pClass…》m_lpszClassName) == 0)
return pClass;
}
TRACE1(〃Error: Class not found: %s n〃; szClassName);
return NULL; // not found
}
149
…………………………………………………………Page 212……………………………………………………………
第篇 勿在浮砂築高台
然后,为了验证这样的动态生成机制的确有效(也就是对象的确被产生了),我让许多
个类别的构造式都输出一段文字,而且在取得对象指针后,真的去调用该对象的一个成
员函数SayHello 。我把SayHello 设计为虚拟函数,所以根据不同的对象类型,会调用
到不同的SayHello 函数,出现不同的输出字符串。
请注意,main 函数中的while 循环必须等到CRuntimeClass::Load 传回NULL 才会停
止,而CRuntimeClass::Load 是在它从整个「类别型录网」中找不到它要找的那个类别
名称时,才传回NULL 。这些都是我为了仿真与示范,所采取的权宜设计。
Frame6 的命令列编译联结动作是(环境变量必须先设定好,请参考第4章的「安装与设
定」一节):
cl my。cpp mfc。cpp
下面是Frame6 的执行结果。粗体表示我(程序执行者)在屏幕上输入的类别名称:
enter a class name。。。 CObject
Error: Trying to create object which is not DECLARE_DYNCREATE
or DECLARE_SERIAL: CObject。
enter a class name。。。 CView
Error: Trying