博主资料

留言 加为好友 收藏

用户名:  oliveccid

个人统计

用户名: oliveccid
等级: 初来乍到
威望: 45
积分: 121
在线时间: 0 小时
日志总数: 12
评论数量: 7
访问次数: 62295
建立时间: 2006-06-27
RSS订阅       手机访问

文章搜索

文章列表

友情链接

最近访问的人:

广州易源服装专卖..
2007-10-29 06:50:39
有点意思
2007-09-27 13:47:08
IIS-Apache详细配..
2007-07-02 02:03:08

日志文章

2006年06月28日 19:19:59

MFC中RTTI技术的实现原理

RTTI-Run Time Type Information

 

1、需求

判断一个对象是否为指定类的实例

 

2、需求分析

2.1、通过类型信息(类的名字)来区分类的类型

如:对于类A的实例a,可以通过其类型信息(类的名字)判断a就是A的实例;

2.2、通过类型信息的关联来体现类之间的继承关系

如:类A继承自类B、类B继承自类C、类C继承自类D,对于A的实例a,可以判断出它也可以作为BCD的实例;

2.3、对同一个类的所有实例而言,它们取到的是同一份类型信息;

2.4、在类被实例化之前就可以取到该类的类型信息;

 

3、设计

3.1、为需要支持RTTI的类设计一个基类(CObject),作为类之间继承关系链中的起点;

3.2、设计一个类(CRuntimeClass)来保存类和父类的类型信息,该类提供一个方法用来判断给定的类型信息是否与类及父类的类型信息匹配(IsDerivedFrom);

3.3、基类(CObject)的基本设计

l         增加一个CRuntimeClass类型的静态变量,为该变量赋值(类的名字/父类的类型变量的指针);

l         增加一个方法(GetRuntimeClass)来取得CRuntimeClass类型的静态变量;

l         一个可进行类型判断的方法(IsKindOf),可以由继承类直接使用;

3.4、需要支持RTTI的类的基本设计

l         增加一个CRuntimeClass类型的静态变量,为该变量赋值(类的名字/父类的类型变量的指针);

l         增加一个方法(GetRuntimeClass)来取得CRuntimeClass类型的静态变量;

3.5、使用方法

l         判断cChildName对象是否为CName的实例

CChildName cChildName;

BOOL bIsName=cChildName.IsKindOf((CRuntimeClass*) (&CName:: classCName));

 

4、普通实现

4.1CRuntimeClass

struct CRuntimeClass

{

LPCSTR m_lpszClassName; //类的名字

CRuntimeClass* m_pBaseClass; //父类类型信息

BOOL IsDerivedFrom(const CRuntimeClass* pBaseClass) const

{   

const CRuntimeClass* pClassThis = this;

while (pClassThis != NULL)   //循环取父类的类型信息

{

if (pClassThis == pBaseClass) return TRUE;

pClassThis = pClassThis->m_pBaseClass;

}

return FALSE;

}

};

4.2CObject

class CObject

{

public:

//取得静态变量classCObject的指针

virtual CRuntimeClass* GetRuntimeClass() const

{

return (CRuntimeClass*) (&CObject:: classCObject);

};

public:

BOOL IsKindOf(const CRuntimeClass* pClass) const

{    

CRuntimeClass* pClassThis = GetRuntimeClass();

return pClassThis->IsDerivedFrom(pClass);

};

public:

//静态变量,保存类型信息,基类的父类类型对象指针为空

      static const CRuntimeClass classCObject= { "CObject", NULL };

};

4.3CName

class CName:: CObject

{

public:

//取得静态变量classCName的指针

virtual CRuntimeClass* GetRuntimeClass() const

{

return (CRuntimeClass*) (&CName:: classCName);

};

public:

//静态变量,保存类型信息,父类类型对象指定为继承的类的静态类型对象

      static const CRuntimeClass classCName = { "CName ", (CRuntimeClass*) (&CObject:: classCObject) };

};

 

5、通过宏来简化实现

5.1、宏的定义

l         RUNTIME_CLASS

#define RUNTIME_CLASS(class_name) ((CRuntimeClass*)(&class_name::class##class_name))

l         DECLARE_DYNAMIC

#define DECLARE_DYNAMIC(class_name) \

public: static const CRuntimeClass class##class_name; \

        virtual CRuntimeClass* GetRuntimeClass() const; \

l         IMPLEMENT_DYNAMIC

#define IMPLEMENT_DYNAMIC(class_name, base_class_name) \

             IMPLEMENT_RUNTIMECLASS(class_name, base_class_name)

#define IMPLEMENT_RUNTIMECLASS(class_name, base_class_name) \

const CRuntimeClass class_name::class##class_name = { \

                    #class_name, RUNTIME_CLASS(base_class_name) }; \

             CRuntimeClass* class_name::GetRuntimeClass() const \

                    { return RUNTIME_CLASS(class_name); } \

5.2、简化后的实现

l         判断cChildName对象是否为CName的实例

CChildName cChildName;

BOOL bIsName=cChildName.IsKindOf(RUNTIME_CLASS (CName));

l         CName

//头文件

class CName:: CObject

{

DECLARE_DYNAMIC(CName)

};

//源文件

IMPLEMENT_DYNAMIC(CName, CObject)

 

6、总结

6.1、静态变量的使用

l         确保类被实例化之前就可以取到该类的类型信息

l         确保对同一个类的所有实例而言,它们取到的是同一份类型信息

6.2、宏的使用;

6.3、为弄清原理,对MFC的源代码进行了简化;

 

 

 

类别: C++ |  评论(0) |  浏览(2411) |  收藏
-20楼 [楼主][匿名] Says:
-21楼 [楼主][匿名] Says:
-22楼 [楼主][匿名] Says:
-23楼 [楼主][匿名] Says:
发表评论