一个简单的RTTI实现
RTTI是"Runtime Type Information"的缩写,意思是:运行时类型信息.它提供了运行时确定对象类型的方法.
最近在写的一些东西,不想使用MFC之类的框架,但是却在很多地方需要根据名称确定指针的转换类型或者利用抽象工厂生产抽象的类对象指针...
我很不喜欢不容易维护且难看的"switch case",而C++本身的RTTI功能又显得很单薄...看来只有自己写一个C++的RTTI实现了.
RTTI.h:
- //////////////////////////////////////////////////////////////////
- // RTTI - RTTI 支持
- //
- // Author: 木头云
- // Blog: http://hi.baidu.com/markl22222
- // E-Mail: mark.lonr@tom.com
- // Version: 1.0.1001.1823
- //////////////////////////////////////////////////////////////////
- #ifndef __STDCPX_RTTI_H__
- #define __STDCPX_RTTI_H__
- #if _MSC_VER > 1000
- #pragma once
- #endif // _MSC_VER > 1000
- //////////////////////////////////////////////////////////////////
- // RTTI 起始类声明
- class CBaseObj;
- //////////////////////////////////////////////////////////////////
- // type_id 自增量
- extern int TypeInfoOrder;
- // 类型信息结构
- struct TypeInfo
- {
- typedef CBaseObj* (*pfn_dc)(GCAlloc& gc);
- LPTSTR className;
- int type_id;
- TypeInfo* pBaseClass;
- pfn_dc m_pfnCreateObject; // NULL => abstract class
- CBaseObj* CreateObject(GCAlloc& gc)
- {
- if( m_pfnCreateObject == NULL ) return NULL;
- return (*m_pfnCreateObject)(gc);
- }
- bool operator == (const TypeInfo& info)
- {
- return this == &info;
- }
- bool operator != (const TypeInfo& info)
- {
- return this != &info;
- }
- };
- //////////////////////////////////////////////////////////////////
- // 向工厂注册 TypeInfo 指针
- #define REGISTER_TYPEINFO(key, inf) /
- CTypeInfoFactory::GetInstance()->RegisterTypeInfo(key, inf)
- // 从工厂得到 TypeInfo 指针
- #define GET_TYPEINFO(key) /
- CTypeInfoFactory::GetInstance()->GetTypeInfo(key)
- // TypeInfo 指针单例工厂
- class CTypeInfoFactory sealed
- {
- private:
- typedef Map<tstring, TypeInfo*> key_map;
- private:
- key_map dc_funcs;
- private:
- CTypeInfoFactory(GCAlloc& gc) : dc_funcs(gc) {}
- public:
- // 获得工厂单例
- static CTypeInfoFactory* GetInstance()
- {
- // 仅用于RTTI时不需要考虑线程同步问题
- // 为了提高效率, 此处不加线程同步锁
- static GCAlloc gc;
- static CTypeInfoFactory instance(gc);
- return &instance;
- }
- // 向工厂注册一个类名
- bool RegisterTypeInfo(LPCTSTR c_key, TypeInfo* inf)
- {
- if( c_key == NULL ) return false;
- tstring key(c_key);
- if( dc_funcs.find(key) == dc_funcs.end() )
- {
- dc_funcs.insert( key_map::value_type(key, inf) );
- return true;
- }
- else
- return false;
- }
- // 从工厂获得一个 TypeInfo
- TypeInfo* GetTypeInfo(LPCTSTR c_key)
- {
- if( c_key == NULL ) return NULL;
- tstring key(c_key);
- if( dc_funcs.find(key) == dc_funcs.end() )
- return NULL;
- else
- return dc_funcs[key];
- }
- };
- //////////////////////////////////////////////////////////////////
- // Base Typedef 宏定义
- #define DEF_BASETYPE(base_name) /
- public: /
- typedef base_name Base;
- //////////////////////////////////////////////////////////////////
- // TYPEINFO 类型信息宏定义
- #define TYPEINFO_OF_CLS(cls_name) (cls_name::GetTypeInfoClass())
- #define TYPEINFO_OF_OBJ(obj_name) (obj_name.GetTypeInfo())
- #define TYPEINFO_OF_PTR(ptr_name) (ptr_name->GetTypeInfo())
- #define TYPEINFO_MEMBER(cls_name) rttiTypeInfo
- //////////////////////////////////////////////////////////////////
- // 类的 RTTI 宏定义
- #define DECLARE_TYPEINFO_CLS(cls_name, base_name) /
- DEF_BASETYPE(base_name) /
- public: /
- virtual int GetTypeID() { return TYPEINFO_MEMBER(cls_name).type_id; } /
- virtual LPCTSTR GetTypeName() { return TYPEINFO_MEMBER(cls_name).className; } /
- virtual TypeInfo& GetTypeInfo() { return TYPEINFO_MEMBER(cls_name); } /
- static TypeInfo& GetTypeInfoClass() { return TYPEINFO_MEMBER(cls_name); } /
- private: /
- static TypeInfo TYPEINFO_MEMBER(cls_name);
- #define DECLARE_TYPEINFO_NULL(cls_name) /
- public: /
- virtual int GetTypeID() { return TYPEINFO_MEMBER(cls_name).type_id; } /
- virtual LPCTSTR GetTypeName() { return TYPEINFO_MEMBER(cls_name).className; } /
- virtual TypeInfo& GetTypeInfo() { return TYPEINFO_MEMBER(cls_name); } /
- static TypeInfo& GetTypeInfoClass() { return TYPEINFO_MEMBER(cls_name); } /
- private: /
- static TypeInfo TYPEINFO_MEMBER(cls_name); /
- public: /
- bool IsKindOf(TypeInfo& cls);
- // dynamically typeinfo
- #define DECLARE_DYNAMIC_CLS(cls_name, base_name) /
- DECLARE_TYPEINFO_CLS(cls_name, base_name)
- #define DECLARE_DYNAMIC_NULL(cls_name) /
- DECLARE_TYPEINFO_NULL(cls_name)
- // dynamically constructable
- #define DECLARE_DYNCREATE_CLS(cls_name, base_name) /
- DECLARE_DYNAMIC_CLS(cls_name, base_name) /
- public: /
- static CBaseObj* CreateObject(GCAlloc& gc); /
- private: /
- static bool m_bRegSuccess;
- #define DECLARE_DYNCREATE_NULL(cls_name) /
- DECLARE_DYNAMIC_NULL(cls_name) /
- public: /
- static CBaseObj* CreateObject(GCAlloc& gc); /
- private: /
- static bool m_bRegSuccess;
- /////////////////////////////////
- #define IMPLEMENT_TYPEINFO_CLS(cls_name, base_name, pfn_new) /
- TypeInfo cls_name::TYPEINFO_MEMBER(cls_name) = /
- { _T(#cls_name), TypeInfoOrder++, &(base_name::GetTypeInfoClass()), pfn_new };
- #define IMPLEMENT_TYPEINFO_NULL(cls_name, pfn_new) /
- TypeInfo cls_name::TYPEINFO_MEMBER(cls_name) = /
- { _T(#cls_name), TypeInfoOrder++, NULL, pfn_new }; /
- bool cls_name::IsKindOf(TypeInfo& cls) /
- { /
- TypeInfo* p = &(this->GetTypeInfo()); /
- while( p != NULL ) /
- { /
- if( p->type_id == cls.type_id ) /
- return true; /
- p = p->pBaseClass; /
- } /
- return false; /
- }
- // dynamically typeinfo
- #define IMPLEMENT_DYNAMIC_CLS(cls_name, base_name) /
- IMPLEMENT_TYPEINFO_CLS(cls_name, base_name, NULL)
- #define IMPLEMENT_DYNAMIC_NULL(cls_name) /
- IMPLEMENT_TYPEINFO_NULL(cls_name, NULL)
- // dynamically constructable
- #define IMPLEMENT_DYNCREATE_CLS(cls_name, base_name) /
- IMPLEMENT_TYPEINFO_CLS(cls_name, base_name, cls_name::CreateObject) /
- CBaseObj* cls_name::CreateObject(GCAlloc& gc) /
- { return /*new cls_name*/GC_NEW(gc, cls_name); } /
- bool cls_name::m_bRegSuccess = /
- REGISTER_TYPEINFO( _T(#cls_name), &(cls_name::TYPEINFO_MEMBER(cls_name)) );
- #define IMPLEMENT_DYNCREATE_NULL(cls_name) /
- IMPLEMENT_TYPEINFO_NULL(cls_name, cls_name::CreateObject) /
- CBaseObj* cls_name::CreateObject(GCAlloc& gc) /
- { return /*new cls_name*/GC_NEW(gc, cls_name); } /
- bool cls_name::m_bRegSuccess = /
- REGISTER_TYPEINFO( _T(#cls_name), &(cls_name::TYPEINFO_MEMBER(cls_name)) );
- //////////////////////////////////////////////////////////////////
- // 动态指针转换宏定义
- #define DYNAMIC_CAST(cls_name, object_ptr) /
- dynamic_cast_t<cls_name>( TYPEINFO_OF_CLS(cls_name), object_ptr )
- // 动态对象创建宏定义
- #define DYNAMIC_CREATE(cls_name, key, gc) /
- dynamic_create_t<cls_name>( key, gc )
- //////////////////////////////////////////////////////////////////
- // RTTI 起始类
- class CBaseObj
- {
- DECLARE_DYNCREATE_NULL(CBaseObj)
- };
- //////////////////////////////////////////////////////////////////
- // 动态指针转换函数模板
- template <class T>
- inline T* dynamic_cast_t(TypeInfo& cls, CBaseObj* ptr)
- {
- if( ptr )
- return ptr->IsKindOf(cls) ? (T*)ptr : NULL;
- else
- return NULL;
- }
- // 动态对象创建函数
- template <class T>
- inline T* dynamic_create_t(LPCTSTR c_key, GCAlloc& gc)
- {
- if( c_key == NULL ) return NULL;
- TypeInfo* inf = GET_TYPEINFO(c_key);
- if( inf )
- return DYNAMIC_CAST( T, inf->CreateObject(gc) );
- else
- return NULL;
- }
- //////////////////////////////////////////////////////////////////
- #endif // __STDCPX_RTTI_H__
RTTI.cpp:
- #include "stdafx.h"
- #ifndef __STDCPX_RTTI_H__
- #include "detail//RTTI.h"
- #endif
- //////////////////////////////////////////////////////////////////
- // type_id 自增量初始化
- extern int TypeInfoOrder = 0;
- // CBaseObj 成员定义
- IMPLEMENT_DYNCREATE_NULL(CBaseObj)
在"struct TypeInfo"中我用到了许式伟的StdExt库,若要单独使用的话需要把"Map"改为"map",即使用stl的map完成同样的功能,并删除掉带有"GCAlloc"的语句.
此RTTI在使用上类似MFC的RTTI,所有需要用到RTTI功能的类必须继承自"class CBaseObj".
使用示例:
Show.h:
- class CShow : public CBaseObj
- {
- DECLARE_DYNAMIC_CLS(CShow, CBaseObj)
- public:
- CShow() {}
- virtual ~CShow() {}
- };
Show.cpp:
- IMPLEMENT_DYNAMIC_CLS(C
http://blog.csdn.net/markl22222/article/details/5308167
一个简单的RTTI实现的更多相关文章
- 哪种缓存效果高?开源一个简单的缓存组件j2cache
背景 现在的web系统已经越来越多的应用缓存技术,而且缓存技术确实是能实足的增强系统性能的.我在项目中也开始接触一些缓存的需求. 开始简单的就用jvm(java托管内存)来做缓存,这样对于单个应用服务 ...
- 在Openfire上弄一个简单的推送系统
推送系统 说是推送系统有点大,其实就是一个消息广播功能吧.作用其实也就是由服务端接收到消息然后推送到订阅的客户端. 思路 对于推送最关键的是服务端向客户端发送数据,客户端向服务端订阅自己想要的消息.这 ...
- ASP.NET Aries 入门开发教程2:配置出一个简单的列表页面
前言: 朋友们都期待我稳定地工作,但创业公司若要躺下,也非意念可控. 若人生注定了风雨飘摇,那就雨中前行了. 最机开始看聊新的工作机会,欢迎推荐,创业公司也可! 同时,趁着自由时间,抓紧把这系列教程给 ...
- 计算机程序的思维逻辑 (60) - 随机读写文件及其应用 - 实现一个简单的KV数据库
57节介绍了字节流, 58节介绍了字符流,它们都是以流的方式读写文件,流的方式有几个限制: 要么读,要么写,不能同时读和写 不能随机读写,只能从头读到尾,且不能重复读,虽然通过缓冲可以实现部分重读,但 ...
- 如何开发一个简单的HTML5 Canvas 小游戏
原文:How to make a simple HTML5 Canvas game 想要快速上手HTML5 Canvas小游戏开发?下面通过一个例子来进行手把手教学.(如果你怀疑我的资历, A Wiz ...
- CSharpGL(24)用ComputeShader实现一个简单的图像边缘检测功能
CSharpGL(24)用ComputeShader实现一个简单的图像边缘检测功能 效果图 这是红宝书里的例子,在这个例子中,下述功能全部登场,因此这个例子可作为使用Compute Shader的典型 ...
- CSharpGL(23)用ComputeShader实现一个简单的ParticleSimulator
CSharpGL(23)用ComputeShader实现一个简单的ParticleSimulator 我还没有用过Compute Shader,所以现在把红宝书里的例子拿来了,加入CSharpGL中. ...
- 应用OpenMP的一个简单的设计模式
小喵的唠叨话:最近很久没写博客了,一是因为之前写的LSoftmax后馈一直没有成功,所以在等作者的源码.二是最近没什么想写的东西.前两天,在预处理图片的时候,发现处理200w张图片,跑了一晚上也才处理 ...
- 用php实现一个简单的链式操作
最近在读<php核心技术与最佳实践>这本书,书中第一章提到用__call()方法可以实现一个简单的字符串链式操作,比如,下面这个过滤字符串然后再求长度的操作,一般要这么写: strlen( ...
随机推荐
- jquery easyUI DataGrid 初始化的时候就显示可排序的字段
在使用easy ui的列表中,想要标记可以排序的字段,使用户一看页面就知道哪些是可以点击排序的. 给可排序的字段添加 图标在列名后面.不可排序的字段还和原来一样. 步骤: 你需要一个图标 , 你需要给 ...
- 关于Application Cache
http://blog.csdn.net/fwwdn/article/details/8082433 http://www.cnblogs.com/blackbird/archive/2012/06/ ...
- ZRender源码分析6:Shape对象详解之路径
开始 说到这里,就不得不提SVG的路径操作了,因为ZRender完全的模拟了SVG原生的path元素的用法,很是强大. 关于SVG的Path,请看这里: Path (英文版) 或者 [MDN]SVG教 ...
- Android NIO(Noblocking I/O非阻塞I/O)小结
参考:http://www.cnblogs.com/cpcpc/archive/2011/06/27/2123009.html 对于Android的网络通讯性能的提高,我们可以使用Java上高性能的N ...
- HTML5中的服务器‘推送’技术 -Server-Sent Events
转帖:http://www.developersky.net/thread-63-1-1.html 一直以来,HTTP协议都是严格遵循Request-Response模型的.客户端发送一个Reques ...
- rabbitmq问题之HTTP access denied: user 'guest' - User can only log in via localhost
问题: 昨天安装rabbitmq(3.3.4版本)服务,并启用rabbitmq_management插件去管理rabbitmq服务,但是在访问管理界面使用guest用户登录时出现login faile ...
- Cortex-M3和Cortex-M4 Fault异常应用之一 ----- 基础知识
1. 摘要 Cortex-M内核实现了一个高效异常处理模块,可以捕获非法内存访问和数个程序错误条件.本应用笔记从程序员角度描述Cortex-M Fault异常,并且讲述在软件开发周期中的Fault用法 ...
- Windows Azure 社区新闻综述(#69 版)
欢迎查看最新版本的每周综述,其中包含有关云计算和 WindowsAzure 的社区推动新闻.内容和对话. 以下是过去一周基于您的反馈汇集在一起的内容: 文章.视频和博客文章 · 使用 Azur ...
- MVC中使用AuthorizeAttribute做身份验证操作【转】
http://blog.csdn.net/try530/article/details/7782704 代码顺序为:OnAuthorization-->AuthorizeCore-->Ha ...
- 问题解决——Group Box控件遮挡其它控件
转载请保持文章的完整性并显要地注明出处 本文链接:http://blog.csdn.net/wlsgzl/article/details/38042301 ====================== ...