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

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

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

RTTI.h:

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

RTTI.cpp:

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

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

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

使用示例:

Show.h:

  1. class CShow : public CBaseObj
  2. {
  3. DECLARE_DYNAMIC_CLS(CShow, CBaseObj)
  4. public:
  5. CShow() {}
  6. virtual ~CShow() {}
  7. };

Show.cpp:

  1. IMPLEMENT_DYNAMIC_CLS(C

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

一个简单的RTTI实现的更多相关文章

  1. 哪种缓存效果高?开源一个简单的缓存组件j2cache

    背景 现在的web系统已经越来越多的应用缓存技术,而且缓存技术确实是能实足的增强系统性能的.我在项目中也开始接触一些缓存的需求. 开始简单的就用jvm(java托管内存)来做缓存,这样对于单个应用服务 ...

  2. 在Openfire上弄一个简单的推送系统

    推送系统 说是推送系统有点大,其实就是一个消息广播功能吧.作用其实也就是由服务端接收到消息然后推送到订阅的客户端. 思路 对于推送最关键的是服务端向客户端发送数据,客户端向服务端订阅自己想要的消息.这 ...

  3. ASP.NET Aries 入门开发教程2:配置出一个简单的列表页面

    前言: 朋友们都期待我稳定地工作,但创业公司若要躺下,也非意念可控. 若人生注定了风雨飘摇,那就雨中前行了. 最机开始看聊新的工作机会,欢迎推荐,创业公司也可! 同时,趁着自由时间,抓紧把这系列教程给 ...

  4. 计算机程序的思维逻辑 (60) - 随机读写文件及其应用 - 实现一个简单的KV数据库

    57节介绍了字节流, 58节介绍了字符流,它们都是以流的方式读写文件,流的方式有几个限制: 要么读,要么写,不能同时读和写 不能随机读写,只能从头读到尾,且不能重复读,虽然通过缓冲可以实现部分重读,但 ...

  5. 如何开发一个简单的HTML5 Canvas 小游戏

    原文:How to make a simple HTML5 Canvas game 想要快速上手HTML5 Canvas小游戏开发?下面通过一个例子来进行手把手教学.(如果你怀疑我的资历, A Wiz ...

  6. CSharpGL(24)用ComputeShader实现一个简单的图像边缘检测功能

    CSharpGL(24)用ComputeShader实现一个简单的图像边缘检测功能 效果图 这是红宝书里的例子,在这个例子中,下述功能全部登场,因此这个例子可作为使用Compute Shader的典型 ...

  7. CSharpGL(23)用ComputeShader实现一个简单的ParticleSimulator

    CSharpGL(23)用ComputeShader实现一个简单的ParticleSimulator 我还没有用过Compute Shader,所以现在把红宝书里的例子拿来了,加入CSharpGL中. ...

  8. 应用OpenMP的一个简单的设计模式

    小喵的唠叨话:最近很久没写博客了,一是因为之前写的LSoftmax后馈一直没有成功,所以在等作者的源码.二是最近没什么想写的东西.前两天,在预处理图片的时候,发现处理200w张图片,跑了一晚上也才处理 ...

  9. 用php实现一个简单的链式操作

    最近在读<php核心技术与最佳实践>这本书,书中第一章提到用__call()方法可以实现一个简单的字符串链式操作,比如,下面这个过滤字符串然后再求长度的操作,一般要这么写: strlen( ...

随机推荐

  1. 利用R语言打造量化分析平台

    利用R语言打造量化分析平台 具体利用quantmod包实现对股票的量化分析 1.#1.API读取在线行情2.#加载quantmod包3.if(!require(quantmod)){4. instal ...

  2. jquery easyUI DataGrid 初始化的时候就显示可排序的字段

    在使用easy ui的列表中,想要标记可以排序的字段,使用户一看页面就知道哪些是可以点击排序的. 给可排序的字段添加 图标在列名后面.不可排序的字段还和原来一样. 步骤: 你需要一个图标 , 你需要给 ...

  3. QTcpSocket 及 TCP粘包分析

    ----我的生活,我的点点滴滴!! 这两天用Qt简单的实现一个tcp多线程client,在此记录下知识. 一.长连接与短连接 1.长连接 Client方与Server方先建立通讯连接,连接建立后不断开 ...

  4. 为Delphi程序增加UAC功能

    相关资料:http://bbs.csdn.net/topics/320071356# 操作方法: 在Source\VCL目录下应该有这样两个文件sample.manifest和WindowsXP.rc ...

  5. 怎样学习使用libiconv库

    怎样学习使用libiconv库 - My Study My Study About My Learn or Study etc. 怎样学习使用libiconv库 By Cnangel on Febru ...

  6. leetcode_question_111 Minimum Depth of Binary Tree

    Given a binary tree, find its minimum depth. The minimum depth is the number of nodes along the shor ...

  7. wx.BookCtrlBase

    wx.BookCtrlBase A book control is a convenient way of displaying multiple pages of information, disp ...

  8. java 泛型深入之Set有用工具 各种集合泛型深入使用演示样例,匿名内部类、内部类应用于泛型探讨

    java 泛型深入之Set有用工具 各种集合泛型深入使用演示样例,匿名内部类.内部类应用于泛型探讨 //Sets.java package org.rui.generics.set; import j ...

  9. oracle11g+ef+vs2013做的项目在部署的时候碰到的问题

    最近公司做一个项目,用到了ef和oracle11g,开发工具用的是vs2013,开发完成后,在本机上完美运行,但是,当到了要到服务器上部署的时候,就出了问题,服务器环境是server08R2,开发环境 ...

  10. 第六章SignalR的服务器广播

    第六章SignalR的服务器广播 1.概述: VS可以通过 Microsoft.AspNet.SignalR.Sample NuGet包来安装一个简单的模拟股票行情应用.在本教程的第一部分,您将从头开 ...