
日志文章

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,可以判断出它也可以作为B、C、D的实例; 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.1、CRuntimeClass 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.2、CObject 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.3、CName 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的源代码进行了简化; |



RSS订阅
手机访问
一共有 0 条评论