C 實現反射(二)

2021-07-27 12:46:04 字數 2844 閱讀 2651

新部落格鏈結

找了一些資料,參考了 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 模板類提供作為註冊的簡單封裝...