分享
 
 
 

MFC rtti 学习笔记

王朝vc·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

1.

核心类CRuntimeClass.

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

};

CRuntimeClass的关键字段:

1.1 m_lpszClassName:

类型名,所有实现rtti的类都要通过这个名称来创建. 命名规范为 _lpsz + 类名

如要创建类CObject,则对应的CRuntimeClass类为classCObject,classCObject的m_lpszClassName字段值为szCObject。

1.2 m_pfnCreateObject:

函数指针, 其申明为: CObject *(PASCAL* m_pfnCreateObject)();

1.3 CreateObject()函数

其申明为: CObject* CreateObject();

1.4 pFirstClass 和 m_pNextClass

其申明为:

static CRuntimeClass* pFirstClass; // start of class list

CRuntimeClass* m_pNextClass;

注意: pFirstClass被申明为static,因为这个属性在编译的时候就要被赋初值

而m_pNextClass是非static的

CRuntimeClass通过这2个属性来构建出所有支持的类型链表。

------------------------- 举例 ---------------------------------

假如要创建一个类Ca,必须从CObject继承.

2.

在类Ca中加入一个CRuntimeClass类型的静态成员变量classCa (变量名称必须依据命名规范 class + 类名):

public: static CRuntimeClass classCa ;

3.

把classCa成员变量的指针加入到CRuntime的类链表中(该类链表中的元素都从CRuntime继承)。

4.

初始化静态变量classCa:

CRuntimeClass Ca::classCa = {

"_lpszCa",

sizeof(Ca),

0xFFFF,

Ca::CreateObject, //函数指针, classCa的m_pfnCreateObject成员变量的值被指定为Ca::CreateObject。

// NULL 表示Ca是虚类

(&CObject::classCObject),

0

};

5.

在CRuntimeClass中定义一个Load函数,其功能是根据参数在CRuntimeClass的类链表中查找是否存在这个类,如果存在,则返回这个类指针

CRuntimeClass* * CRuntimeClass::Load( char szClassName ){

CRuntimeClass* pClass;

for (pClass = pFirstClass; pClass != NULL; pClass = pClass->m_pNextClass)

{

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

return pClass;

}

//类链表中没有这个类

return NULL;

}

6.

调用Load函数,并把参数设为"classCa"

CRuntimeClass* pClassRef;

pClassRef = CRuntimeClass::Load();

//本例得到得是Ca中静态成员变量classCa 得指针。

然后调用classCa的 CreateObject()函数

CObject* pOb;

pOb = pClassRef->CreateObject();

pOb->doSomething();

//-----------------------------------------------------

核心宏:

所有的类型申明和定义都是通过宏来实现的,无法通过函数来实现,因为所有的类型必须在编译的时候就确定下来。

这些宏可以分为2类:

1. 构建CRuntimeClass中类型链表的宏

1.1 DECLARE_DYNAMIC(class_name):

#define DECLARE_DYNAMIC(class_name) public: static CRuntimeClass class##class_name; virtual CRuntimeClass* GetRuntimeClass() const;

1.2 IMPLEMENT_DYNAMIC(class_name, base_class_name)

#define IMPLEMENT_DYNAMIC(class_name, base_class_name) _IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, NULL)

2. 通过类型名称创建类的宏

2.1 DECLARE_DYNCREATE(class_name)

#define DECLARE_DYNCREATE(class_name) DECLARE_DYNAMIC(class_name) static CObject* PASCAL CreateObject();

2.2 IMPLEMENT_DYNCREATE(class_name, base_class_name)

#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)

注意:第二类宏(通过类型名称创建类的宏)包含了对应的第一类宏(declare和 implement),所以,如果用了第二类宏,就不需要再用第一类宏了。

也即: 如果用了第二类宏来申明和实现类的动态创建,则自动完成了动态类链表的创建。

但是,如果某些动态类是不能创建的,只能申明,则只要使用第一类宏。比如一下虚类(如CObject(它是很多具体类的父类)),在CRuntimeClass的类链表中存在这个类,但是不能创建它,因为对它没有使用第二类宏(即它没有CreateObject函数)。

3. 另一个重要的宏_IMPLEMENT_RUNTIMECLASS

在IMPLEMENT_DYNAMIC和IMPLEMENT_DYNCREATE宏中,都调用了宏_IMPLEMENT_RUNTIMECLASS,但是对于最好一个参数(表示createobject的函数指针)使用了不同的参数值().

IMPLEMENT_DYNAMIC 使用NULL, IMPLEMENT_DYNCREATE宏使用class_name::CreateObject.

NULL 表示没有createobject函数的实现, 也表示了对应的类是一个虚类。

_IMPLEMENT_RUNTIMECLASS宏的定义(很负责,其实它才是真正的核心宏):

#define _IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew) static char _lpsz##class_name[] = #class_name; CRuntimeClass class_name::class##class_name = { _lpsz##class_name, sizeof(class_name), wSchema, pfnNew, RUNTIME_CLASS(base_class_name), NULL }; static AFX_CLASSINIT _init_##class_name(&class_name::class##class_name); CRuntimeClass* class_name::GetRuntimeClass() const { return &class_name::class##class_name; }

其中含有一个 静态的类(structure)AFX_CLASSINIT的实例对象,由这个对象的构造函数来把类型链表串起来.

AFX_CLASSINIT的申明和定义如下:

struct AFX_CLASSINIT

{

AFX_CLASSINIT(CRuntimeClass* pNewClass);

};

AFX_CLASSINIT::AFX_CLASSINIT(CRuntimeClass* pNewClass)

{

pNewClass->m_pNextClass = CRuntimeClass::pFirstClass;

CRuntimeClass::pFirstClass = pNewClass;

}

//-----------------------------------------------------

重点总结:

功能是通过宏来实现的

基本上所有的变量都是static,

要定义好类的命名规范,这是宏能正确达到预定功能的前提。

//------------------------------------------------------

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有