您的位置:首页 > 其它

一个简单的RTTI实现

2015-03-06 10:45 169 查看
RTTI是"Runtime Type Information"的缩写,意思是:运行时类型信息.它提供了运行时确定对象类型的方法.

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

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

RTTI.h:

[cpp] view
plaincopy

//////////////////////////////////////////////////////////////////

// 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:

[cpp] view
plaincopy

#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:

[cpp] view
plaincopy

class CShow : public CBaseObj

{

DECLARE_DYNAMIC_CLS(CShow, CBaseObj)

public:

CShow() {}

virtual ~CShow() {}

};

Show.cpp:

[cpp] view
plaincopy

IMPLEMENT_DYNAMIC_CLS(CShow, CBaseObj)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: