按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
“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 to create object which is not DECLARE_DYNCREATE
or DECLARE_SERIAL: CView。
enter a class name。。。 CMyView
CWnd Constructor
CMyView Constructor
Hello CMyView
enter a class name。。。 CMyFrameWnd
CWnd Constructor
CFrameWnd Constructor
CMyFrameWnd Constructor
Hello CMyFrameWnd
enter a class name。。。 CMyDoc
CMyDoc Constructor
Hello CMyDoc
150
…………………………………………………………Page 213……………………………………………………………
第3章 MFC 六大關鍵技術之模擬
enter a class name。。。 CWinApp
Error: Trying to create object which is not DECLARE_DYNCREATE
or DECLARE_SERIAL: CWinApp。
enter a class name。。。 CJjhou (故意输入一个不在「类别型录网」中的类别名称)
Error: Class not found: CJjhou (程序结束)
Frame6 范例程序
MFC。H
#0001 #define BOOL int
#0002 #define TRUE 1
#0003 #define FALSE 0
#0004 #define LPCSTR LPSTR
#0005 typedef char* LPSTR;
#0006 #define UINT int
#0007 #define PASCAL _stdcall
#0008 #define TRACE1 printf
#0009
#0010 #include
#0011 #include
#0012 #include
#0013
#0014 class CObject;
#0015
#0016 struct CRuntimeClass
#0017 {
#0018 // Attributes
#0019 LPCSTR m_lpszClassName;
#0020 int m_nObjectSize;
#0021 UINT m_wSchema; // schema number of the loaded class
#0022 CObject* (PASCAL* m_pfnCreateObject)(); // NULL =》 abstract class
#0023 CRuntimeClass* m_pBaseClass;
#0024
#0025 CObject* CreateObject();
#0026 static CRuntimeClass* PASCAL Load();
#0027
#0028 // CRuntimeClass objects linked together in simple list
#0029 static CRuntimeClass* pFirstClass; // start of class list
#0030 CRuntimeClass* m_pNextClass; // linked list of registered classes
#0031 };
#0032
#0033 struct AFX_CLASSINIT
151
…………………………………………………………Page 214……………………………………………………………
第篇 勿在浮砂築高台
#0034 { AFX_CLASSINIT(CRuntimeClass* pNewClass); };
#0035
#0036 #define RUNTIME_CLASS(class_name)
#0037 (&class_name::class##class_name)
#0038
#0039 #define DECLARE_DYNAMIC(class_name)
#0040 public:
#0041 static CRuntimeClass class##class_name;
#0042 virtual CRuntimeClass* GetRuntimeClass() const;
#0043
#0044 #define DECLARE_DYNCREATE(class_name)
#0045 DECLARE_DYNAMIC(class_name)
#0046 static CObject* PASCAL CreateObject();
#0047
#0048 #define _IMPLEMENT_RUNTIMECLASS(class_name; base_class_name; wSchema; pfnNew)
#0049 static char _lpsz##class_name'' = #class_name;
#0050 CRuntimeClass class_name::class##class_name = {
#0051 _lpsz##class_name; sizeof(class_name); wSchema; pfnNew;
#0052 RUNTIME_CLASS(base_class_name); NULL };
#0053 static AFX_CLASSINIT _init_##class_name(&class_name::c