码迷,mamicode.com
首页 > 其他好文 > 详细

一个简单的RTTI实现

时间:2015-12-03 22:45:22      阅读:329      评论:0      收藏:0      [点我收藏+]

标签:

RTTI是"Runtime Type Information"的缩写,意思是:运行时类型信息.它提供了运行时确定对象类型的方法.

最近在写的一些东西,不想使用MFC之类的框架,但是却在很多地方需要根据名称确定指针的转换类型或者利用抽象工厂生产抽象的类对象指针...

我很不喜欢不容易维护且难看的"switch case",而C++本身的RTTI功能又显得很单薄...看来只有自己写一个C++的RTTI实现了.

RTTI.h:

 

[cpp] view plaincopy
 
  1. //////////////////////////////////////////////////////////////////  
  2. // RTTI - RTTI 支持  
  3. //  
  4. // Author:  木头云  
  5. // Blog:    http://hi.baidu.com/markl22222  
  6. // E-Mail:  mark.lonr@tom.com  
  7. // Version: 1.0.1001.1823  
  8. //////////////////////////////////////////////////////////////////  
  9.   
  10. #ifndef __STDCPX_RTTI_H__  
  11. #define __STDCPX_RTTI_H__  
  12.   
  13. #if _MSC_VER > 1000  
  14. #pragma once  
  15. #endif // _MSC_VER > 1000  
  16.   
  17. //////////////////////////////////////////////////////////////////  
  18.   
  19. // RTTI 起始类声明  
  20. class CBaseObj;  
  21.   
  22. //////////////////////////////////////////////////////////////////  
  23.   
  24. // type_id 自增量  
  25. extern int TypeInfoOrder;  
  26.   
  27. // 类型信息结构  
  28. struct TypeInfo  
  29. {  
  30.     typedef CBaseObj* (*pfn_dc)(GCAlloc& gc);  
  31.   
  32.     LPTSTR      className;  
  33.     int         type_id;  
  34.     TypeInfo*   pBaseClass;  
  35.     pfn_dc      m_pfnCreateObject;  // NULL => abstract class  
  36.   
  37.     CBaseObj* CreateObject(GCAlloc& gc)  
  38.     {  
  39.         if( m_pfnCreateObject == NULL ) return NULL;  
  40.         return (*m_pfnCreateObject)(gc);  
  41.     }  
  42.   
  43.     bool operator == (const TypeInfo& info)  
  44.     {  
  45.         return this == &info;  
  46.     }  
  47.     bool operator != (const TypeInfo& info)  
  48.     {  
  49.         return this != &info;  
  50.     }  
  51. };  
  52.   
  53. //////////////////////////////////////////////////////////////////  
  54.   
  55. // 向工厂注册 TypeInfo 指针  
  56. #define REGISTER_TYPEINFO(key, inf) /  
  57.     CTypeInfoFactory::GetInstance()->RegisterTypeInfo(key, inf)  
  58. // 从工厂得到 TypeInfo 指针  
  59. #define GET_TYPEINFO(key)           /  
  60.     CTypeInfoFactory::GetInstance()->GetTypeInfo(key)  
  61.   
  62. // TypeInfo 指针单例工厂  
  63. class CTypeInfoFactory sealed  
  64. {  
  65. private:  
  66.     typedef Map<tstring, TypeInfo*> key_map;  
  67.   
  68. private:  
  69.     key_map dc_funcs;  
  70.   
  71. private:  
  72.     CTypeInfoFactory(GCAlloc& gc) : dc_funcs(gc) {}  
  73.   
  74. public:  
  75.     // 获得工厂单例  
  76.     static CTypeInfoFactory* GetInstance()  
  77.     {  
  78.         // 仅用于RTTI时不需要考虑线程同步问题  
  79.         // 为了提高效率, 此处不加线程同步锁  
  80.         static GCAlloc gc;  
  81.         static CTypeInfoFactory instance(gc);  
  82.         return &instance;  
  83.     }  
  84.   
  85.     // 向工厂注册一个类名  
  86.     bool RegisterTypeInfo(LPCTSTR c_key, TypeInfo* inf)  
  87.     {  
  88.         if( c_key == NULL ) return false;  
  89.         tstring key(c_key);  
  90.         if( dc_funcs.find(key) == dc_funcs.end() )  
  91.         {  
  92.             dc_funcs.insert( key_map::value_type(key, inf) );  
  93.             return true;  
  94.         }  
  95.         else  
  96.             return false;  
  97.     }  
  98.   
  99.     // 从工厂获得一个 TypeInfo  
  100.     TypeInfo* GetTypeInfo(LPCTSTR c_key)  
  101.     {  
  102.         if( c_key == NULL ) return NULL;  
  103.         tstring key(c_key);  
  104.         if( dc_funcs.find(key) == dc_funcs.end() )  
  105.             return NULL;  
  106.         else  
  107.             return dc_funcs[key];  
  108.     }  
  109. };  
  110.   
  111. //////////////////////////////////////////////////////////////////  
  112.   
  113. // Base Typedef 宏定义  
  114. #define DEF_BASETYPE(base_name)                                                         /  
  115. public:                                                                                 /  
  116.     typedef base_name Base;  
  117.   
  118. //////////////////////////////////////////////////////////////////  
  119.   
  120. // TYPEINFO 类型信息宏定义  
  121.   
  122. #define TYPEINFO_OF_CLS(cls_name)       (cls_name::GetTypeInfoClass())  
  123. #define TYPEINFO_OF_OBJ(obj_name)       (obj_name.GetTypeInfo())  
  124. #define TYPEINFO_OF_PTR(ptr_name)       (ptr_name->GetTypeInfo())  
  125.   
  126. #define TYPEINFO_MEMBER(cls_name)       rttiTypeInfo  
  127.   
  128. //////////////////////////////////////////////////////////////////  
  129.   
  130. // 类的 RTTI 宏定义  
  131.   
  132. #define DECLARE_TYPEINFO_CLS(cls_name, base_name)                                       /  
  133.     DEF_BASETYPE(base_name)                                                             /  
  134. public:                                                                                 /  
  135.     virtual int GetTypeID()             { return TYPEINFO_MEMBER(cls_name).type_id; }   /  
  136.     virtual LPCTSTR GetTypeName()   { return TYPEINFO_MEMBER(cls_name).className; } /  
  137.     virtual TypeInfo& GetTypeInfo()     { return TYPEINFO_MEMBER(cls_name); }           /  
  138.     static TypeInfo& GetTypeInfoClass() { return TYPEINFO_MEMBER(cls_name); }           /  
  139. private:                                                                                /  
  140.     static TypeInfo TYPEINFO_MEMBER(cls_name);  
  141.   
  142. #define DECLARE_TYPEINFO_NULL(cls_name)                                                 /  
  143. public:                                                                                 /  
  144.     virtual int GetTypeID()             { return TYPEINFO_MEMBER(cls_name).type_id; }   /  
  145.     virtual LPCTSTR GetTypeName()   { return TYPEINFO_MEMBER(cls_name).className; } /  
  146.     virtual TypeInfo& GetTypeInfo()     { return TYPEINFO_MEMBER(cls_name); }           /  
  147.     static TypeInfo& GetTypeInfoClass() { return TYPEINFO_MEMBER(cls_name); }           /  
  148. private:                                                                                /  
  149.     static TypeInfo TYPEINFO_MEMBER(cls_name);                                          /  
  150. public:                                                                                 /  
  151.     bool IsKindOf(TypeInfo& cls);  
  152.   
  153. // dynamically typeinfo  
  154.   
  155. #define DECLARE_DYNAMIC_CLS(cls_name, base_name)                                        /  
  156.     DECLARE_TYPEINFO_CLS(cls_name, base_name)  
  157.   
  158. #define DECLARE_DYNAMIC_NULL(cls_name)                                                  /  
  159.     DECLARE_TYPEINFO_NULL(cls_name)  
  160.   
  161. // dynamically constructable  
  162.   
  163. #define DECLARE_DYNCREATE_CLS(cls_name, base_name)                                      /  
  164.     DECLARE_DYNAMIC_CLS(cls_name, base_name)                                            /  
  165. public:                                                                                 /  
  166.     static CBaseObj* CreateObject(GCAlloc& gc);                                         /  
  167. private:                                                                                /  
  168.     static bool m_bRegSuccess;  
  169.   
  170. #define DECLARE_DYNCREATE_NULL(cls_name)                                                /  
  171.     DECLARE_DYNAMIC_NULL(cls_name)                                                      /  
  172. public:                                                                                 /  
  173.     static CBaseObj* CreateObject(GCAlloc& gc);                                         /  
  174. private:                                                                                /  
  175.     static bool m_bRegSuccess;  
  176.   
  177.     /////////////////////////////////  
  178.   
  179. #define IMPLEMENT_TYPEINFO_CLS(cls_name, base_name, pfn_new)                            /  
  180.     TypeInfo cls_name::TYPEINFO_MEMBER(cls_name) =                                      /  
  181.         { _T(#cls_name), TypeInfoOrder++, &(base_name::GetTypeInfoClass()), pfn_new };  
  182.   
  183. #define IMPLEMENT_TYPEINFO_NULL(cls_name, pfn_new)                                      /  
  184.     TypeInfo cls_name::TYPEINFO_MEMBER(cls_name) =                                      /  
  185.         { _T(#cls_name), TypeInfoOrder++, NULL, pfn_new };                              /  
  186.     bool cls_name::IsKindOf(TypeInfo& cls)                                              /  
  187.     {                                                                                   /  
  188.         TypeInfo* p = &(this->GetTypeInfo());                                            /  
  189.         while( p != NULL )                                                              /  
  190.         {                                                                               /  
  191.             if( p->type_id == cls.type_id )                                              /  
  192.                 return true;                                                            /  
  193.             p = p->pBaseClass;                                                           /  
  194.         }                                                                               /  
  195.         return false;                                                                   /  
  196.     }  
  197.   
  198. // dynamically typeinfo  
  199.   
  200. #define IMPLEMENT_DYNAMIC_CLS(cls_name, base_name)                                      /  
  201.     IMPLEMENT_TYPEINFO_CLS(cls_name, base_name, NULL)  
  202.   
  203. #define IMPLEMENT_DYNAMIC_NULL(cls_name)                                                /  
  204.     IMPLEMENT_TYPEINFO_NULL(cls_name, NULL)  
  205.   
  206. // dynamically constructable  
  207.   
  208. #define IMPLEMENT_DYNCREATE_CLS(cls_name, base_name)                                    /  
  209.     IMPLEMENT_TYPEINFO_CLS(cls_name, base_name, cls_name::CreateObject)                 /  
  210.     CBaseObj* cls_name::CreateObject(GCAlloc& gc)                                       /  
  211.     { return /*new cls_name*/GC_NEW(gc, cls_name); }                                    /  
  212.     bool cls_name::m_bRegSuccess =                                                      /  
  213.         REGISTER_TYPEINFO( _T(#cls_name), &(cls_name::TYPEINFO_MEMBER(cls_name)) );  
  214.   
  215. #define IMPLEMENT_DYNCREATE_NULL(cls_name)                                              /  
  216.     IMPLEMENT_TYPEINFO_NULL(cls_name, cls_name::CreateObject)                           /  
  217.     CBaseObj* cls_name::CreateObject(GCAlloc& gc)                                       /  
  218.     { return /*new cls_name*/GC_NEW(gc, cls_name); }                                    /  
  219.     bool cls_name::m_bRegSuccess =                                                      /  
  220.         REGISTER_TYPEINFO( _T(#cls_name), &(cls_name::TYPEINFO_MEMBER(cls_name)) );  
  221.   
  222. //////////////////////////////////////////////////////////////////  
  223.   
  224. // 动态指针转换宏定义  
  225. #define DYNAMIC_CAST(cls_name, object_ptr)                                              /  
  226.     dynamic_cast_t<cls_name>( TYPEINFO_OF_CLS(cls_name), object_ptr )  
  227.   
  228. // 动态对象创建宏定义  
  229. #define DYNAMIC_CREATE(cls_name, key, gc)                                               /  
  230.     dynamic_create_t<cls_name>( key, gc )  
  231.   
  232. //////////////////////////////////////////////////////////////////  
  233.   
  234. // RTTI 起始类  
  235. class CBaseObj  
  236. {  
  237.     DECLARE_DYNCREATE_NULL(CBaseObj)  
  238. };  
  239.   
  240. //////////////////////////////////////////////////////////////////  
  241.   
  242. // 动态指针转换函数模板  
  243. template <class T>  
  244. inline T* dynamic_cast_t(TypeInfo& cls, CBaseObj* ptr)  
  245. {  
  246.     if( ptr )  
  247.         return ptr->IsKindOf(cls) ? (T*)ptr : NULL;  
  248.     else  
  249.         return NULL;  
  250. }  
  251.   
  252. // 动态对象创建函数  
  253. template <class T>  
  254. inline T* dynamic_create_t(LPCTSTR c_key, GCAlloc& gc)  
  255. {  
  256.     if( c_key == NULL ) return NULL;  
  257.     TypeInfo* inf = GET_TYPEINFO(c_key);  
  258.     if( inf )  
  259.         return DYNAMIC_CAST( T, inf->CreateObject(gc) );  
  260.     else  
  261.         return NULL;  
  262. }  
  263.   
  264. //////////////////////////////////////////////////////////////////  
  265.   
  266. #endif  // __STDCPX_RTTI_H__  

 

RTTI.cpp:

 

[cpp] view plaincopy
 
  1. #include "stdafx.h"  
  2.   
  3. #ifndef __STDCPX_RTTI_H__  
  4. #include "detail//RTTI.h"  
  5. #endif  
  6.   
  7. //////////////////////////////////////////////////////////////////  
  8.   
  9. // type_id 自增量初始化  
  10. extern int TypeInfoOrder = 0;  
  11.   
  12. // CBaseObj 成员定义  
  13. IMPLEMENT_DYNCREATE_NULL(CBaseObj)  

 

在"struct TypeInfo"中我用到了许式伟的StdExt库,若要单独使用的话需要把"Map"改为"map",即使用stl的map完成同样的功能,并删除掉带有"GCAlloc"的语句.

此RTTI在使用上类似MFC的RTTI,所有需要用到RTTI功能的类必须继承自"class CBaseObj".

使用示例:

Show.h:

 

[cpp] view plaincopy
 
  1. class CShow : public CBaseObj  
  2. {  
  3.     DECLARE_DYNAMIC_CLS(CShow, CBaseObj)  
  4.   
  5. public:  
  6.     CShow() {}  
  7.     virtual ~CShow() {}  
  8. };  

 

Show.cpp:

 

[cpp] view plaincopy
 
  1. IMPLEMENT_DYNAMIC_CLS(C

 http://blog.csdn.net/markl22222/article/details/5308167

一个简单的RTTI实现

标签:

原文地址:http://www.cnblogs.com/findumars/p/5017713.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!