.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 ;
#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::tostring(monday), monday);
getchar();
return 0;
輸出結果如下:
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 ;
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
#include
#include // for runtime_error
#endif
template class enumhelper
public:
static const char * tostring(enum_t e)
for(int i = 0; i < _countof(enumhelper::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::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::s_allenums =\
to_enum_item(enum_list)\
template<> const char* enumhelper::s_allenumnames[_countof(enumhelper::s_allenums)];\
template<> char enumhelper::s_singleenumstr = stringize(enum_list) ;\
template<> const char * enumhelper::s_typename = (enumhelper::splitenumdefstring(), #enum_type_name);
c so 反射 c 實現反射機制
下午接了個阿里 面試,當時剛剛睡醒,感覺有點懵。大腦莫名當機狀態,很多問題沒有表述清楚,有乙個關於 c 如何實現反射機制的問題,感覺蠻有意思,當時雖然回答了用函式指標和工廠模式,但是表述並不當,細節也沒有想清楚。晚上抽空簡單實現了一發 file name reflector.cpp author x...
c so 反射 C 反射的方法與實現
1.什麼是反射?反射是程式獲取自身資訊的能力 2.反射有什麼用?可以用於動態建立型別,跨語言跨平台資料互動,持久化,序列化等等。3.反射包含哪些功能?至少包含以下功能 列舉所有member 獲取member的name和type 能夠get set member 4.有哪些反射方法?反射主要有3種實現...
c 實現反射機制
c 中反射機制比較常見,而c 中沒有該機制。使用c 實現反射機制,主要利用了工廠模式程序物件的生產。itest.h 基類test.h 繼承類helper.h 幫助類main.cpp 主函式入口檔案 pragma once include using namespace std class itest...