注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

还东国的博客

行之苟有恒,久久自芬芳

 
 
 

日志

 
 

(转载)C++实现反射机制  

2014-01-27 22:26:19|  分类: C++(VC)编程 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

C++实现反射机制

http://www.cnblogs.com/quark/archive/2011/10/12/2208241.html

.NET下的很多技术都是基于反射机制来实现的,反射让.NET平台下的语言变得得心应手。最简单的,比如枚举类型,我们我可以很容易的获得一个枚举变量的数值以及其名称字符串。

 

可是,在C++中,枚举变量本质上和一个整形变量没有区别,我们很难获取一个枚举变量的名称字符串。

 

其实在C++中,我们可以通过宏来实现类似反射的机制。

 

接下来,我想总结一下如何在C++中实现一个类似于C#枚举类型的方法。

 

 

 

   __VA_ARGS__

 

使用__VA_ARGS__,我们可以定义带可变参数的宏,举个例子:

 

#define MY_PRINTF(…) printf(__VA_ARGS__)

 

这样我们写

 

MY_PRINTF("hello, %s”, "world");

 

就等价于

 

printf("hello, %s”, "world");

 

 

 

宏的"##"符号

 

"##"符号的作用是在可变参数的个数为0时,消除参数前面的逗号:

 

#define MY_PRINTF(fs, …) printf(fs, ##__VA_ARGS__)

 

我们这样调用:

 

MY_PRINTF(“Hello, World”);

 

等价于

 

printf(“Hello, World”);

 

另外"##"符号还能够去掉括号,但是我现在还不是很明白,为什么能够做到这一点:

 

#define ENUM_COTENTS(...)  __VA_ARGS__

#define ENUM_CONTENT_REMOVE_PARENTHESIS(a)  ENUM_COTENTS##a

#define DEFINE_ENUM(name)  enum name { ENUM_CONTENT_REMOVE_PARENTHESIS(ENUM_LIST) };

#define ENUM_LIST (Sunday=1,Monday=2)

DEFINE_ENUM(WeekDay)

 

 

宏的"#"符号

 

"#"符号的作用是“字符化”代码:

 

#define MY_STRINGLIZED_MACRO(str) #str

int helloWorld = 0;

printf(MY_STRINGLIZED_MACRO(helloWorld));    // output: helloWorld

 

 

 

利用C++宏实现简单的.NET枚举类型

 

我做了一个简单的用例,最终示例代码如下:

 

#include "DefineEnum.h"

#define ENUM_LIST                                   \

        ENUM_NAME(Sunday     ENUM_VALUE(10)),       \

        ENUM_NAME(Monday     ENUM_VALUE(Sunday+1)),     \

        ENUM_NAME(Tuesday    ENUM_VALUE(123)),      \

        ENUM_NAME(Wednesday  ENUM_VALUE(10)) ,      \

        ENUM_NAME(Thursday   ENUM_VALUE(7)),        \

        ENUM_NAME(Friday     ENUM_VALUE(8)),        \

        ENUM_NAME(Saturday   ENUM_VALUE(12))

 

DEFINE_ENUM(WeekDay);

 

#include "RegisterEnum.h"

REGISTER_ENUM(WeekDay);

 

 

int main()

{

    printf("%s is %d.", EnumHelper<WeekDay>::ToString(Monday), Monday);

    getchar();

    return 0;

}

 

 

输出结果如下:

 

image

 

 

 

DefineEnum.h

 

#undef ENUM_LIST

 

#undef ENUM_NAME

#define ENUM_NAME(...)  __VA_ARGS__

 

 

#undef ENUM_VALUE

#define ENUM_VALUE(val) = val

 

#define ENUM_COTENTS(...)  __VA_ARGS__

 

#define DEFINE_ENUM(name)  enum name { ENUM_COTENTS(ENUM_LIST) };

 

 

RegisterEnum.h

 


#include "ReflectEnum.h"

 

#undef ENUM_VALUE

#define ENUM_VALUE(val)

 

#define REGISTER_ENUM(name)  REFLECT_ENUM(name, ENUM_LIST )

 

 

ReflectEnum.h



#ifndef REFLECT_ENUM_INCLUDE_GUARD

 

#include <string>

#include <cstring>

#include <stdexcept> // for runtime_error

 

#endif

 

template <typename Enum_T> class EnumHelper

{

public:

    static const char * ToString(Enum_T e)

    {

        for(int i = 0; i < _countof(EnumHelper<Enum_T>::s_allEnums); i++)

        {

            if( s_allEnums[i] == e)

                return s_allEnumNames[i];

        }

        return NULL;

    }

 

private:

    static const char * s_typeName;

    static Enum_T s_allEnums[];

    static char s_singleEnumStr[];

    static const char * s_allEnumNames[];

 

    static void SplitEnumDefString()

    {

        char * p = s_singleEnumStr;

        while( isspace(*p) ) p++;

        for(int i = 0; i < _countof(EnumHelper<Enum_T>::s_allEnums); i++)

        {

            s_allEnumNames[i] = p;

            while( *p == '_' || isdigit(*p) || isalpha(*p) ) p++;

            bool meet_comma = ( *p == ',' );

            *p++ = '\0';

            if( !meet_comma )

            {

                while( *p && *p != ',') p++;

                if( *p ) p++;

            }

            while( *p && isspace(*p) ) p++;

        }

    }

};

 

#define TO_ENUM_ITEM(...)  __VA_ARGS__

#define STRINGIZE(...)  #__VA_ARGS__

 

#define REFLECT_ENUM(enum_type_name, enum_list)                                                                         \

template<> enum_type_name EnumHelper<enum_type_name>::s_allEnums[] =                                                    \

{                                                                                                                       \

    TO_ENUM_ITEM(enum_list)                                                                                             \

};                                                                                                                      \

template<> const char* EnumHelper<enum_type_name>::s_allEnumNames[_countof(EnumHelper<enum_type_name>::s_allEnums)];  \

template<> char EnumHelper<enum_type_name>::s_singleEnumStr[] = STRINGIZE(enum_list) ;                                  \

template<> const char * EnumHelper<enum_type_name>::s_typeName = (EnumHelper<enum_type_name>::SplitEnumDefString(), #enum_type_name);

  评论这张
 
阅读(590)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017