MFC运行时动态类实现
MFC运行时动态类实现MD DocUmEnT: 4/2/2016 12:28:57 AM by Jimbowhy技术背景MFC是微软为数不多,公开源代码发布的一个软件框架,深入的技术分析可以通过侯俊杰先生的《深入浅出MFC》,资料确实非常赞,作者真可谓知无言,言无不尽。虽然现在有许多关于MFC过时与否的讨论,个人觉得没有必要参与其中,所有事物其实都会有过时的那天,人也是如此。对于没有掌握的一种技
MFC运行时动态类实现
- MD DocUmEnT: 4/2/2016 12:28:57 AM by Jimbowhy
技术背景
MFC是微软为数不多,公开源代码发布的一个软件框架,深入的技术分析可以参考侯俊杰先生的《深入浅出MFC》,资料确实非常赞,作者真可谓知无言,言无不尽。虽然现在有许多关于MFC过时与否的讨论,个人觉得没有必要参与其中,所有事物其实都会有过时的那天,人也是如此。对于没有掌握的一种技术,那就是新的,并非过时,过时只是对于前面那批会MFC却又不用MFC做事的人来说的。我并没有完全掌握MFC,但我也没有必要完全去掌握MFC,只是喜欢MFC,喜欢学习其中的实现技术。MFC并不一定能减轻程序开发的负担,相反它可能会很大程序上增加程序人员的工作量,如果不适当地应用这种技术。
运行时类型信息 RTTI,Run-Time Type Information 和动态类型 Dynmic Class 作为MFC六大核心机制其中之二,联系非常紧密,就像消息映射 Message Mapping 和命令传递 Command Routing一样结合紧密。其余两项核心技术,MFC初始化与持久化 Persistence 则相对独立。而消息映射机制和动态类型则是我认为最有趣的两大技术,C++标准也有RTTI的实现,但MFC比它更早。
实现代码
要掌握动态类型光靠文字描述效果不怎样,其实写下代码最有说服力,从代码的角度理解动态类型的工作原理是十分贴切的。实现完整的动态类型可以粗分为四个步骤,首先是创建动态类型基础,它可以记录系统所有动态类型信息,其作用相当于数据库,代码实现上它就是一张一维链表,通过表头一直接驳到最原始的基类。有了基础类型,接下来就需要一个特殊的结构体用来记录这些动态类的链表信息。第三步就是最重要的一步,通过宏将前面两部分内容组织到具体的类定义及实现过程中。最后,在定义类时,引用这些宏定义来完成动态类型的定义,以下是具体代码实现:
基础类定义
/*****************************************************************************\
Runtime Type Information demo by Jimbowhy 2016/4/1 23:50
Compiler: Visual C++ 6, TDM-GCC 3.7.1
This programme is a demonstration of how MFC implementates RuntimeClass
\*****************************************************************************/
#include <iostream>
#include <cstring>
using namespace std;
/*
* --------------=========== Step I: Runtime Classs ===========---------------
*/
class CRuntimeClass {
public:
char * name; // keep order for the first 4 members
int size;
void * (* constructor)();
CRuntimeClass* pBase;
CRuntimeClass* pNext;
static CRuntimeClass* theFirst;
static void * CreateObject(char *);
bool isKindOf(const CRuntimeClass*) const;
};
CRuntimeClass *CRuntimeClass::theFirst = NULL;
bool CRuntimeClass::isKindOf(const CRuntimeClass *c) const {
const CRuntimeClass *p = this;
while(p){
if( c==p ) return true;
p = p->pBase;
}
return false;
}
void *CRuntimeClass::CreateObject(char * classname){
CRuntimeClass *c = CRuntimeClass::theFirst;
while(c){
CRuntimeClass &cr = *c;
if( strcmp(classname, cr.name) == 0 ) break;
c = cr.pNext;
}
CRuntimeClass &cr = *c;
if( c==NULL) throw "Not a valid dynamic class specified!";
if( cr.constructor==NULL ) return NULL;
return cr.constructor();
}
辅助结构
/*
* --------------=========== Step II: Runtime Auxiliary ===========---------------
*/
struct AFX_CLASSINIT {
AFX_CLASSINIT(CRuntimeClass *);
};
AFX_CLASSINIT::AFX_CLASSINIT(CRuntimeClass* pNew){
pNew->pNext = CRuntimeClass::theFirst;
CRuntimeClass::theFirst = pNew;
}
宏结构
/*
* --------------============ Step IV: Macro Auxiliary ===========---------------
*/
#define DECLARE_DYNAMIC \
static CRuntimeClass Class; \
static AFX_CLASSINIT ClassInit;
#define IMPLEMENT_DYNAMIC(ClassName, Base) \
CRuntimeClass ClassName::Class = { #ClassName, sizeof(ClassName), NULL, &Base::Class };\
AFX_CLASSINIT ClassName::ClassInit(&ClassName::Class);
#define DECLARE_DYNCREATE \
DECLARE_DYNAMIC \
static void * CreateObject();
#define IMPLEMENT_DYNCREATE(ClassName, Base) \
void *ClassName::CreateObject(){ return new ClassName(); } \
CRuntimeClass ClassName::Class = { #ClassName, sizeof(ClassName), ClassName::CreateObject, &Base::Class };\
AFX_CLASSINIT ClassName::ClassInit(&ClassName::Class);
应用动态类
/*
* --------------=========== Step V: Use Runtime Class ===========---------------
*/
class Shape {
public:
Shape() {
cout << "Raw shape" << endl;
}
DECLARE_DYNCREATE
};
IMPLEMENT_DYNCREATE(Shape, Shape)
class Trangle: public Shape {
public:
Trangle (){
cout << "Trangle" << endl;
}
DECLARE_DYNCREATE
};
IMPLEMENT_DYNCREATE(Trangle, Shape)
class Ellipse: public Shape {
public:
Ellipse(){
cout << "Ellipse" << endl;
}
DECLARE_DYNAMIC
};
IMPLEMENT_DYNAMIC(Ellipse, Shape)
测试程序入口
/*
* ---------------============== Programme Entry ==============----------------
*/
void main(){
char classname[256];
cout << "Try RuntimeClass, dynamicaly create, Shape, Trangle, Ellipse, and more...\n";
cout << "Type what class you want now:";
while(1)
try{
cin >> classname;
void * o = CRuntimeClass::CreateObject(classname);
if( o==NULL ){
cout << "Not a dynamicaly create class specified!" << endl;
return;
}
}catch(char* m){
cout << m << endl;
}
}
以上就是一个完整的动态类实现过程,至于运行时类型信息机制其实也已经是五脏俱全了,只要添加typeid,isKindOf之类的运算符就可以很好地解决运行时类型问题。
全文完。
更多推荐
所有评论(0)