深入浅出MFC学习笔记第三章MFC六大关键技术之仿真类型识别动态创建.docx

上传人:b****7 文档编号:8850067 上传时间:2023-02-02 格式:DOCX 页数:31 大小:22.99KB
下载 相关 举报
深入浅出MFC学习笔记第三章MFC六大关键技术之仿真类型识别动态创建.docx_第1页
第1页 / 共31页
深入浅出MFC学习笔记第三章MFC六大关键技术之仿真类型识别动态创建.docx_第2页
第2页 / 共31页
深入浅出MFC学习笔记第三章MFC六大关键技术之仿真类型识别动态创建.docx_第3页
第3页 / 共31页
深入浅出MFC学习笔记第三章MFC六大关键技术之仿真类型识别动态创建.docx_第4页
第4页 / 共31页
深入浅出MFC学习笔记第三章MFC六大关键技术之仿真类型识别动态创建.docx_第5页
第5页 / 共31页
点击查看更多>>
下载资源
资源描述

深入浅出MFC学习笔记第三章MFC六大关键技术之仿真类型识别动态创建.docx

《深入浅出MFC学习笔记第三章MFC六大关键技术之仿真类型识别动态创建.docx》由会员分享,可在线阅读,更多相关《深入浅出MFC学习笔记第三章MFC六大关键技术之仿真类型识别动态创建.docx(31页珍藏版)》请在冰豆网上搜索。

深入浅出MFC学习笔记第三章MFC六大关键技术之仿真类型识别动态创建.docx

深入浅出MFC学习笔记第三章MFC六大关键技术之仿真类型识别动态创建

第三章:

MFC六大关键技术之仿真:

类型识别

深入理解MFC的内部运行原理,是本次学习《深入浅出MFC》的主要目的。

要模仿的六大技术包括:

1:

MFC程序的初始化过程。

2:

RTTI(Runtimetypeidentification)运行时类型识别。

3:

Dynamiccreation动态创建

4:

Persistence永久保存

5:

消息映射

6:

消息传递。

RTTI(运行时类型识别)

IsKindOf能够侦测某个对象是否属于某种类。

即判断某一对象所属的类是否是父类或当前类;

要达到动态类型识别的能力,必须在构建类继承体系时记录必要的信息,这被称为类型型录表。

MFC以链表的方式建立了此表。

类型型录表的每个元素为CRuntimeClass类型,其定义为:

[cpp]viewplaincopy

1classCRuntimeClass

2

3{

4

5public:

6

7LPCSTRm_lpszClassName;//对象所属类名

8

9Intm_nObjectSize;//对象大小

10

11UINTm_wSchema;//模式号

12

13CObject*(PASCAL*m_pfnCreateObject)();//构建函数抽象类为NULL

14

15CRuntimeClass*pBaseClasss;//基类CRuntimeClass对象指针。

16

17StaticCRuntimeClass*pFirstClass;//链表头指针。

18

19CRuntimeClass*m_pNextClass;//下一指针。

20

21};

MFC使用此类作为每个类的成员变量。

使用宏定义为每个类定义了自己的CRuntimeClass成员变量。

DECLAR_DYNAMIC和IMPLENMENT_DYNAMIC宏

使用这两个宏将CRuntimeClass对象不知不觉放到类之中。

DECLARE_DYNMIC宏定义如下:

[cpp]viewplaincopy

22#defineDELCARE_DYNMIC(class_name)\

23

24public:

\

25

26staticCRuntimeClassclass##class_name\

27

28virtualCRuntimeClass*GetRuntimeClass()const;

##用来告诉编译器把两个字符串连接起来。

如果使用这个宏:

DELCARE_DYNMIC(CView);

那么预编译器将生成下列代码:

[cpp]viewplaincopy

29public:

30

31staticCRuntimeClassclassCView;

32

33virtualCRuntimeClass*GetRuntimeClass()const;

以上代码仅仅是在类中定义CRuntimeClass对象,并定义一个返回CRuntimeClass对象地址的函数。

注意CRuntimeClass是static的,也就是说同一种类继承体系的对象共享一个CRuntimeClass对象。

初始化对象的内容以及建立类型型录表需要使用IMPLEMENT_DYNMIC宏。

[cpp]viewplaincopy

34#defineIMPLEMENT_DYNMIC(class_name,base_class_name)\

35

36_IMPLEMENT_RUNTIMECLASS(class_name,base_class_name,0xFFFF,NULL);

37

38_IMPLEMENT_RUNTIMECLASS又是一个宏,它定义如下:

39

40#define_IMPLEMENT_RUNTIMECLASS(class_name,\

41

42base_class_name,wSchema,pfnNew)\

43

44staticchar_lpsz##class_name[]=#class_name;\

45

46CRuntimeClassclass_name:

:

class##class_name=\

47

48{_lpsz##class_name,sizeof(class_name),\

49

50wSchema,pfnNew,\

51

52RUNTIME_CLASS(base_class_name),NULL\

53

54};

55

56staticAFX_CLASSINIT_init##class_name\

57

58(&class_name:

:

class##class_name);\

59

60CRuntimeClass*class_name:

:

GetRuntimeClass()const\

61

62{\

63

64return&class_name:

:

class##classname;\

65

66}

67

68#defineRUNTIME_CLASS(class_name)\

69

70(&class_name:

:

class##class_name);

AFX_CLASSINIT是一个类,看着跟宏定义似的,这样做很容易让人迷惑。

它用于将本节点连接到类型型录表,定义如下:

[cpp]viewplaincopy

71classAFX_CLASSINIT

72

73{

74

75public:

76

77AFX_CLASSINIT(CRuntimeClass*pNewClass)//构造函数

78

79{

80

81pNewClass->m_pNextClass=CRuntime:

:

pFirstClass;

82

83CRuntimeClass:

:

pFirstClass=pNewClass;

84

85}

86

87};

用法:

[cpp]viewplaincopy

88classCWnd:

publicCCmdTarget

89

90{

91

92public:

93

94DECLARE_DYNAMIC(CWnd);

95

96

97};

IMPLEMENT_DYNMIC(CWnd,CCmdTarget);

代码展开后为;

[cpp]viewplaincopy

98classCWnd:

publicCCmdTarget

99

100{

101

102public:

103

104staticCRuntimeClassclassCView;

105

106virtualCRuntimeClass*GetRuntimeClass()const

107

108

109

110};

111

112

113

114staticchar_lpszCWnd[]="CWnd";

115

116CRuntimeClassCWnd:

:

classCWnd=

117

118{

119

120_lpszCView,sizeof(CWnd),FFFF,NULL,&Wnd:

:

classCWnd,NULL);

121

122};

123

124staticAFX_CLASSINIT_init_CWnd(&CWnd:

:

classCWnd);

125

126{

127

128Return&CWnd:

:

classCWnd;

129

130}

定义宏的过程很复杂,但是一旦定义好之后,在使用时仅仅两句话就可以完成定义CRuntimeClass对象并且连接类型型录链表的工作。

CObject是所有类的基类,也是链表的头,此类应特别定义,不能在CObject内使用定义好的宏。

[cpp]viewplaincopy

131classCObject

132

133{

134

135public:

136

137virtualCRuntimeClass*GetRuntimeClass()const;

138

139staticCRuntimeClassclassCObject;

140

141};

142

143staticcharszCobject[]="CObject";

144

145structCRuntimeClassCObject:

:

classCObject=

146

147{

148

149szCObject,sizeof(CObject),0xFFFF,NULL,NULL,NULL

150

151};

152

153staticAFX_CLASSINIT_init_CObject(&Cobject:

:

classObject);

154

155CRuntimeClass*CObject:

:

GetRuntimeClass()const

156

157{

158

159return&CObject:

:

classCObject;

160

161}

由于CRuntimeClass对象是static成员变量,因此需要在类外初始化。

如果忘记初始化将会报链接错误。

CRuntimeClass*CRuntimeClass:

pFirstClass=NULL;

建好了类类型路表,要实现IsKindOf功能很容易。

首先在CObject加上一个IsKindOf函数,于是所有继承自此类的类都具有类型识别的功能。

能够将某个CRuntimeClass对象与类类型型录中的元素进行比较。

如:

[cpp]viewplaincopy

162classCObject

163

164{

165

166public:

167

168boolIsKindOf(constCRuntimeClass*pClass)const

169

170{

171

172CRuntimeClass*pClassThis=GetRuntimeClass();

173

174while(pClassThis)

175

176{

177

178if(pClassThis==pClass)

179

180returntrue;

181

182pClassThis=pClassThis->m_pBaseClass;//沿着基类寻找。

183

184}

185

186returnfalse;

187

188}

189

190};

如果我们调用CWnd*cw=newCWnd;

cw->IsKindOf(RUNTIME_CLASS(CFrameWnd));

RUNTIME_CLASS实际就是&CFrameWnd:

:

classCFrameWnd,它就是CFrameWnd的static的CRuntimeClass类型成员。

函数内利用GetRuntimeClass取得本类的CRuntimeClass对象的地址,即&CWnd:

classCWnd,然后进行比较。

因为每一类型共用一个static的CRuntimeClass对象,因此属于同于类的CRuntimeClass对象的地址相同。

动态创建

每一类的构建函数可以记录在类型别录中,当获得一个类名称,通过查找类别型录表找出对应的元素,然后调用其构建函数产生新对象。

在CRuntimeClass中m_pfnCreateObject即为构建函数首地址。

为了实现动态创建,需要添加两个宏:

DECLARE_DYNCREATE和IMPLEMENT_DYNCREATE。

如:

[cpp]viewplaincopy

191#defineDECLARE_DYNCREATE(class_name)\

192

193DECLARE_DYNCREATE(class_name)\

194

195staticCObject*PASCALCreateObject();

196

197#defineIMPLEMENT_DYNCREATE(class_name,base_class_name)\

198

199CObject*PASCALclass_name:

:

CreateObject()\

200

201{returnnewclassname;};\

202

203_IMPLEMENT_RUNTIMECLASS(class_name,base_class_name,

204

2050xFFFF,class_name:

:

CreateObject)

以CFrameWnd为例,下列程序代码:

[cpp]viewplaincopy

206classCFrameWnd:

publicCWnd

207

208{

209

210public:

211

212DECLEARE_DYNCREATE(CFrameWnd);

213

214};

IMPLEMENT_DYNCREATE(CFrameWnd,CWnd);

展开如下:

[cpp]viewplaincopy

215classCFrame:

publicCWnd

216

217{

218

219public:

220

221staticCRuntimeClassclassCFrameWnd;

222

223virtualCRuntimeClass*GetRuntimeClass()const;

224

225staticCObject*PASCALCreateObject();

226

227};

228

229CObject_PASCALCFrameWnd:

CreateObject()

230

231{

232

233returnnewCFrameWnd;

234}

235

236staticchar_lpszCFrameWnd[]="CFrameWnd";

237

238CRuntimeClassCFrameClass:

:

classCFrameWnd={

239

240_lpszCFrameWnd,sizeof(CFrameWnd),0xFFFF,CFrameWnd:

:

CreateObject,RUNTIME_CALSS(CWnd),NULL};

241

242staticAFX_CLASSINIT_init_CFrameWnd

243

244(&CFrameWnd:

:

classCFrameWnd);

245

246CRuntimeClass*CFrameWnd:

:

GetRunimeClass()const

247

248{return&CFrameWnd:

:

classCFrameWnd;}

注意对象构建函数为static函数。

为了支持动态创建需要在CRuntimeClass内添加两个函数:

CreateObject和CRuntimeClass:

Load成员函数。

[cpp]viewplaincopy

249CObject*CRuntimeClass:

CreateObject()

250

251{

252

253If(m_pfnCreateObject==NULL)//不支持动态创建。

254

255{

256

257throwruntime_error("此类不支持动态创建");

258

259ReturnNULL;

260

261}

262

263CObject*pObject=(*m_pfnCreateObject)();

264

265ReturnpObject;

266

267}

268

269CRuntimeClass*PASCLCRuntimeClass:

:

Load()

270

271{

272

273CharszClassName[64];

274

275CRuntimeClass*pClass

276

277cout<<"输入一个类名:

";

278

279cin>>szClassName;

280

281for(pClass=pFirstClass;pClass;pClass=pClass->m_pNextClass)

282

283{

284

285if(strcmp(szClassName,pClass->m_lpszClassName)==0)

286

287returnpClass;

288

289returnNULL;

290

291}

292

293}

以下为类型识别及动态创建的完整代码:

[cpp]viewplaincopy

294

18px;">#include

295#include

296#include

297usingnamespacestd;

298

299classCObject;

300classCRuntimeClass

301{

302public:

303char*m_lpszClassName;//对象所属类名

304intm_nObjectSize;//对象大小

305intm_wSchema;//模式号

306CObject*(PASCAL*m_pfnCreateObject)();//构建函数,抽象类为NULL

307CRuntimeClass*m_pBaseClasss;//基类CRuntimeClass对象指针。

308staticCRuntimeClass*pFirstClass;//链表头指针。

static

309CRuntimeClass*m_pNextClass;//下一指针。

310public:

311CObject*CreateObject()

312{

313if(m_pfnCreateObject==NULL)

314{

315cout<<"该类型不支持动态创建!

"<

316returnNULL;

317}

318CObject*pClass=(*m_pfnCreateObject)();

319returnpClass;

320}

321staticCRuntimeClass*Load()

322{

323cout<<"请输入要动态创建的类名:

";

324strings;

325cin>>s;

326for(CRuntimeClass*pClass=pFirstClass;pClass;pClass=pClass->m_pBaseClasss)

327{

328if(pClass->m_lpszClassName==s)

329{

330returnpClass;

331}

332}

333returnNULL;

334}

335};

336

337classAFX_CLASSINIT

338{

339public:

340AFX_CLASSINIT(CRuntimeClass*pNewClass)//构造函数

341{

342pNewClass->m_pNextClass=CRuntimeClass:

:

pFirstClass;

343CRuntimeClass:

:

pFirstClass=pNewClass;

344}

345};

346

347/************************************************************************/

348/*动态类型识别宏定义

349//与CRuntimeClass类中的构建函数相区别。

此处的CreateObject函数在每个类中都以static成员函数存在,用以

350//初始化类型型录表,而CRuntimeClass中的CreateObject用于调用每个类的构建函数。

仅仅是函数名相同罢了。

*/

351/************************************************************************/

352

353#defineDECLARE_DYNAMIC(class_name)\

354public:

\

355staticCRuntimeClassClass##class_name;\

356virtualCRuntimeClass*GetRuntimeClass()const;\

357

358

359#defineDECLARE_DYNCREATE(class_name)\

360DECLARE_DYNAMIC(class_name)\

361staticCObject*PASCALCreateObject();\

362

363#defineRUNTIME_CLASS(class_name)\

364(&class_name:

:

Class##class_name)\

365

366#define_IMPLEMENT_RUNTIMECLASS(class_name,base_class_name,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 农学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1