友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
深入浅出MFC第2版(PDF格式)-第34部分
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!
。。。
IMPLEMENT_DYNAMIC(CMyDoc; CDocument) //
在 程序中这里其实是
MFC IMPLEMENT_DYNCREATE()
// 稍后我便会仿真IMPLEMENT_DYNCREATE() 给你看
。。。
在 程序中这里其实是
IMPLEMENT_DYNAMIC(CMyView; CView) // MFC IMPLEMENT_DYNCREATE()
// 稍后我便会仿真IMPLEMENT_DYNCREATE() 给你看
我不在此列出Frame4 的源代码,你可以在书附光盘片中找到完整的文件。Frame4 的命
令列编译联结动作是(环境变量必须先设定好,请参考第4章的「安装与设定」一节):
cl my。cpp mfc。cpp
以下即是Frame4 的执行结果:
pMyDoc…》IsKindOf(RUNTIME_CLASS(CMyDoc)) 1
pMyDoc…》IsKindOf(RUNTIME_CLASS(CDocument)) 1
pMyDoc…》IsKindOf(RUNTIME_CLASS(CCmdTarget)) 1
pMyDoc…》IsKindOf(RUNTIME_CLASS(CObject)) 1
pMyDoc…》IsKindOf(RUNTIME_CLASS(CWinApp)) 0
pMyDoc…》IsKindOf(RUNTIME_CLASS(CView)) 0
pMyView…》IsKindOf(RUNTIME_CLASS(CView)) 1
pMyView…》IsKindOf(RUNTIME_CLASS(CObject)) 1
pMyView…》IsKindOf(RUNTIME_CLASS(CWnd)) 1
pMyView…》IsKindOf(RUNTIME_CLASS(CFrameWnd)) 0
pMyWnd…》IsKindOf(RUNTIME_CLASS(CFrameWnd)) 1
pMyWnd…》IsKindOf(RUNTIME_CLASS(CWnd)) 1
pMyWnd…》IsKindOf(RUNTIME_CLASS(CObject)) 1
pMyWnd…》IsKindOf(RUNTIME_CLASS(CDocument)) 0
142
…………………………………………………………Page 205……………………………………………………………
第3章 MFC 六大關鍵技術之模擬
Dynamic Creation (动态生成)
基础有了,做什么都好。同样地,有了上述的「类别型录网」,各种应用纷至沓来。其
中一个应用就是解决棘手的动态生成问题。
我已经在第二章描述过动态生成的困难点:你没有办法在程序执行期间,根据动态获得
的一个类别名称(通常来自读档,但我将以屏幕输入为例),要求程序产生一个对象。
上述的「类别型录网」虽然透露出解决此一问题的些微曙光,但是技术上还得加把劲儿。
如果我能够把类别的大小记录在类别型录中,把构造函数(注意,这里并非指C++ 构造
式,而是指即将出现的CRuntimeClass::CreateObject)也记录在类别型录中,当程序在执
行时期获得一个类别名称,它就可以在「类别型录网」中找出对应的元素,然后调用其
构造函数(这里并非指C++ 构造式),产生出对象。
好主意!
类别型录网的元素型式CRuntimeClass 于是有了变化:
// in MFC。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
CRuntimeClass* m_pBaseClass;
CObject* CreateObject();
static CRuntimeClass* PASCAL Load();
// CRuntimeClass objects linked together in simple list
static CRuntimeClass* pFirstClass; // start of class list
CRuntimeClass* m_pNextClass; // linked list of registered classes
};
143
…………………………………………………………Page 206……………………………………………………………
DECLARE_DYNCREATE /IMPLEMENT_DYNCREATE 宏
为了因应CRuntimeClass 中新增的成员变量, 我们再添两个宏,
DECLARE_DYNCREATE 和IMPLEMENT_DYNCREATE:
#define DECLARE_DYNCREATE(class_name)
DECLARE_DYNAMIC(class_name)
static CObject* PASCAL CreateObject();
#define IMPLEMENT_DYNCREATE(class_name; base_class_name)
CObject* PASCAL class_name::CreateObject()
{ return new class_name; }
_IMPLEMENT_RUNTIMECLASS(class_name; base_class_name; 0xFFFF;
class_name::CreateObject)
于是,以CFrameWnd 为例,下列程序代码:
// in header file
class CFrameWnd : public CWnd
{
DECLARE_DYNCREATE(CFrameWnd)
。。。
};
// in implementation file
IMPLEMENT_DYNCREATE(CFrameWnd; CWnd)
就被展开如下(注意,编译器选项/P 可得前置处理结果):
// in header file
class CFrameWnd : public CWnd
{
public:
static CRuntimeClass classCFrameWnd;
virtual CRuntimeClass* GetRuntimeClass() const;
static CObject* PASCAL CreateObject();
。。。
};
// in implementation file
CObject* PASCAL CFrameWnd::CreateObject()
{ return new CFrameWnd; }
144
…………………………………………………………Page 207……………………………………………………………
static char _lpszCFrameWnd'' = 〃CFrameWnd〃;
CRuntimeClass CFrameWnd::classCFrameWnd = {
_lpszCFrameWnd; sizeof(CFrameWnd); 0xFFFF; CFrameWnd::CreateObject;
RUNTIME_CLASS(CWnd); NULL };
static AFX_CLASSINIT _init_CFrameWnd(&CFrameWnd::classCFrameWnd);
CRuntimeClass* CFrameWnd::GetRuntimeClass() const
{ return &CFrameWnd::classCFrameWnd; }
图示如下:
C O b j e c t : : c l a s s C O b j e c t C C m d T a r g e t : : c l a s s C C m d T a r g e t C W i n T h r e a d : : c l a s s C W i n T h r e a d
“ C O b j e c t ” “ C C m d T a r g e t ” “ C W in T h r e a d ”
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
N U L L
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; C
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!