• 一个简单的RTTI实现


    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

  • 相关阅读:
    Java入门:基础算法之从字符串中找到重复的字符
    Java入门:基础算法之产生随机数
    Java入门:基础算法之线性搜索
    Java入门:基础算法之检查奇偶性
    安装hadoop1.2.1集群环境
    Linux上安装JDK
    改变HTML中超链接的显示样式
    【Nutch2.2.1源代码分析之5】索引的基本流程
    【Nutch2.2.1源代码分析之4】Nutch加载配置文件的方法
    java生成UUID通用唯一识别码 (Universally Unique Identifier)
  • 原文地址:https://www.cnblogs.com/findumars/p/5017713.html
Copyright © 2020-2023  润新知