RTTI是"Runtime Type Information"的缩写,意思是:运行时类型信息.它提供了运行时确定对象类型的方法.
最近在写的一些东西,不想使用MFC之类的框架,但是却在很多地方需要根据名称确定指针的转换类型或者利用抽象工厂生产抽象的类对象指针...
我很不喜欢不容易维护且难看的"switch case",而C++本身的RTTI功能又显得很单薄...看来只有自己写一个C++的RTTI实现了.
RTTI.h:
-
- #ifndef __STDCPX_RTTI_H__
- #define __STDCPX_RTTI_H__
-
- #if _MSC_VER > 1000
- #pragma once
- #endif // _MSC_VER > 1000
-
-
- class CBaseObj;
-
-
- extern int TypeInfoOrder;
-
- struct TypeInfo
- {
- typedef CBaseObj* (*pfn_dc)(GCAlloc& gc);
-
- LPTSTR className;
- int type_id;
- TypeInfo* pBaseClass;
- pfn_dc m_pfnCreateObject;
-
- 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;
- }
- };
-
-
- #define REGISTER_TYPEINFO(key, inf) /
- CTypeInfoFactory::GetInstance()->RegisterTypeInfo(key, inf)
- #define GET_TYPEINFO(key) /
- CTypeInfoFactory::GetInstance()->GetTypeInfo(key)
-
- 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()
- {
-
-
- 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* 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];
- }
- };
-
-
- #define DEF_BASETYPE(base_name) /
- public: /
- typedef base_name Base;
-
-
-
- #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
-
-
-
- #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);
-
-
- #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)
-
-
- #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; /
- }
-
-
- #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)
-
-
- #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
- 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
- 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 )
-
-
- 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
-
-
- extern int TypeInfoOrder = 0;
-
- 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:
http://blog.csdn.net/markl22222/article/details/5308167
一个简单的RTTI实现
原文:http://www.cnblogs.com/findumars/p/5017713.html