新部落格鏈結
找了一些資料,參考了 c++反射——開源中國 這篇,做了一些修改和簡化,成為了 version3.
思路其實並不複雜,可以進行反推:
反射是根據類名動態生成類,如果我們有乙個全域性的對映關係,可以從類名得到類的相關資訊 classinfo,包括類的建構函式,那麼我們便能實現這一點。所以我們需要維護乙個map
這樣的結構作為全域性對映,並提供 register 介面作為 map 的註冊操作,只要再定義乙個createobject(const std::string class_name)
,每次在 map 中檢索到對應的 classinfo,然後建立並返回物件,這樣就有了反射的基礎。
那麼createobject
函式返回的型別是什麼呢?因為反射得到的類各不相同,所以我們需要乙個 object 類作為所有反射類的基類,這樣只要返回乙個 object* 指標就好了。
而 classinfo 是作為儲存類資訊的結構,所以我們需要把類名和建立物件的函式指標儲存下來。除此之外,還應提供乙個createobject
的成員函式供呼叫生成類。
最後,classinfo 在**建立和儲存呢?顧名思義,每個 classinfo 物件應該是每個類唯一的,所以我們可以每個類定義乙個 static 的 classinfo 物件。還有,每個類要提供構造自身的介面,這樣才可以把介面儲存到 classinfo 中,供createobject
呼叫。因為這兩點每個反射類都是相似的,可以借助巨集來簡化。
這樣分析完是不是挺簡單的?當然更大的可能是你被我繞暈了。可以看看下面的**,回過頭再看一遍分析,應該就清楚了。:)
// base.h
#ifndef __base_h__
#define __base_h__
#include #include class object;
class classinfo;
typedef object* (*objectconstructorfn)(void);
bool register(classinfo* ci);
class classinfo
// 根據儲存下來的函式指標構造物件
object* createobject() const
~classinfo() {}
public:
std::string class_name_;
objectconstructorfn object_constructor_;
};// 維護全域性的對映關係
static std::map*class_info_map = nullptr;
// 每個反射類的都需要乙個 classinfo 和 createobject
#define declare_class(name) \
protected: \
static classinfo class_info_; \
public: \
static object* createobject();
// class_info 用類名和類的 createobject 函式初始化
// 在每個反射類的 cpp 檔案中使用該巨集
#define implement_class(name) \
classinfo name::class_info_(#name, (objectconstructorfn) name::createobject);\
object* name::createobject()
// 所有反射類的基類
// 用來傳遞反射物件的指標
class object
virtual ~object() {}
// 提供全域性可使用的 createobject 函式,根據類名生成物件
static object* createobject(std::string name);
};implement_class(object)
object* object::createobject(std::string name)
return nullptr;
}// map 的註冊介面
bool register(classinfo* ci)
if (ci)
}}#endif
使用的時候包含該標頭檔案,反射類(例如 a)繼承 object,並在類中加入巨集declare_class(a)
,在類的實現檔案中加入巨集implement_class(a)
,最後建立物件時使用object::createobject("a")
就可以了。
// base_test.cpp
#include#include#include "base.h"
using namespace std;
class a : public object
virtual test()
~a()
};implement_class(a)
class b : public object
virtual test()
~b()
};implement_class(b)
int main()
到這一步我們就真正實現反**,是不是其實並不難?但我還是覺得不夠好:
每個反射類都要繼承於 object,看起來總是有點奇怪,使用的時候要求使用方知道這個用 object 指標來儲存,不甚明朗。
對於我來說,我只想實現根據類名建立物件,所以**其實可以更簡化一點,map 裡直接儲存類名和函式指標的對映就好了,這樣整體會更簡化些。
c so 反射 C 實現反射機制
net下的很多技術都是基於反射機制來實現的,反射讓.net平台下的語言變得得心應手。最簡單的,比如列舉型別,我們我可以很容易的獲得乙個列舉變數的數值以及其名稱字串。可是,在c 中,列舉變數本質上和乙個整形變數沒有區別,我們很難獲取乙個列舉變數的名稱字串。其實在c 中,我們可以通過巨集來實現類似反射的...
c so 反射 c 實現反射機制
下午接了個阿里 面試,當時剛剛睡醒,感覺有點懵。大腦莫名當機狀態,很多問題沒有表述清楚,有乙個關於 c 如何實現反射機制的問題,感覺蠻有意思,當時雖然回答了用函式指標和工廠模式,但是表述並不當,細節也沒有想清楚。晚上抽空簡單實現了一發 file name reflector.cpp author x...
C 實現反射(三)
新部落格鏈結 實現乙個模板類管理類名和類建構函式的對映關係,並提供構造物件的介面,每個基類需要初始化乙個這樣的管理物件。提供乙個對應的 static 模板函式,用來儲存和返回對應的管理物件。使用模板函式和 new 操作符作為每個類的建構函式。實現乙個簡單的 helper 模板類提供作為註冊的簡單封裝...