由於前不久須要作一個合併多個項目代碼,因此須要經過配置文件來控制建立對象,百度用字符串建立對象,搜索半天無果,後來翻看大話設計模式的時候在工廠模式看到一個反射機制,即經過類名建立對象,因此搜索了一下,果真可以找到,因此下載之後分析了哈,進行本身需求進行修改,現整理一下。使用qt5.5.1進行編碼。設計模式
一、定義一個回調函數,用來建立這個類的實例;定義一個哈希,用於保存類名和建立實例的回調函數;編輯器
二、設計一個單例,用於管理哈希。(可用靜態成員變量替換);函數
三、設計一個工廠類,。經過類工廠來動態建立類對象和註冊類;測試
四、建立註冊類,將回調函數存入哈希裏面,類名字作爲map的key值;編碼
五、定義須要建立對象的類,用於測試。.net
首先聲明一個回調函數設計
typedef void* (*fun_ptr)();指針
聲明一個哈希:對象
typedef std::map<const QString, fun_ptr> create_obj_map; //用來保存回調函數指針,經過registClass()函數來實現類名和函數的插入。blog
定義一個單例,用於處理哈希,也能夠定義成一個靜態成員變量,可是以前試過幾回,沒成功,先使用單例吧。
class LazySingleton
{
public:
template<class T>
static T& instance()
{
static T _instance;
return _instance;
}
};
定義一個工廠類,用於經過此獲取哈希,方法registerClass用於插入類名和建立此類的方法,getInstance函數返回哈希中經過回調函數建立的類的實例化,參數爲傳入的類名。
class ClassFactory
{
public:
static void *getInstance(const QString &className);
static void registerClass(const QString &className, fun_ptr fp);
};
void *ClassFactory::getInstance(const QString &className)
{
std::cout << LazySingleton::instance<create_obj_map>().size() << std::endl;
create_obj_map::iterator iter = LazySingleton::instance<create_obj_map>().begin();
create_obj_map::iterator iterEnd = LazySingleton::instance<create_obj_map>().end();
while (iter != iterEnd)
{
if (iter->first == className)
{
return iter->second();
}
iter++;
}
return NULL;
}
void ClassFactory::registerClass(const QString &className, fun_ptr fp)
{
LazySingleton::instance<create_obj_map>().insert(std::make_pair(className, fp));
}
這樣,咱們的單例工廠類就設計完成了。
下面咱們須要設計一個用來動態建立類的類,被建立的類經過本類來向類工廠註冊對象的函數。
class Register
{
public:
Register(const char* className, fun_ptr fp);
};
Register::Register(const char* className, fun_ptr fp)
{
ClassFactory::registerClass(className, fp);
}
該類設計了個宏,用於實現動態建立,後面的類中會用到。
該宏主要爲了實現兩個功能,一個是配合類工廠來建立一個新的類,新的類用於建立傳入的類,一個是將新的類的建立對象的方法註冊到哈希中。
下面先帖代碼:
#define REGISTER(ClassName) \
class Register##ClassName \
{ \
public: \
static void* instance() \
{ \
return new ClassName; \
} \
private: \
static const Register _staticRegister; \
}; \
const Register Register##ClassName::_staticRegister(#ClassName, Register##ClassName::instance);
先經過宏替換,生成一個新類,而且一個靜態方法,用於建立對象。最後一行是用於調用新類的靜態成員變量,經過此靜態成員變量的構造函數,把類註冊到哈希裏(此處感受Register類設計有點多餘,是否能夠考慮直接最後一句調用ClassFactory::registerClass(className, fp);來進行類註冊,後面再來考慮吧),參數,第一個是類名,第二個是新類的建立對象的函數。到這一步,類反射的功能即將要實現了。
下面咱們來設計最後一個類,就是將要被動態建立的類,先帖碼。
class Foo
{
public:
Foo()
{
_id = 1;
_name = "Foo";
}
public:
int _id;
std::string _name;
};
REGISTER(Foo);
Foo類是咱們要動態建立出來的類,REGISTER(Foo)用於把類foo進行宏替換後生成一個新類,用於建立foo的對象的。
到此,全部的準備工做都作好了,接下來就是測試了。
在main中添加代碼:
Foo* foo = static_cast<Foo*>(ClassFactory::getInstance("Foo"));
std::cout << foo->_name << std::endl;
當界面上打印輸出Foo的時候,就證實是成功了。
到此,C++反射的實現講解完成,這類實現方法適合在開發各種的編輯器中去使用,包括微軟的MFC等等。在開發編輯器的階段,並無相應的類,可是使用者想經過在編輯器中傳入類的名字,而後在開發中,根據編輯器傳入的類名,新建一個類去實現的話,這種方法很是適用,更多的用法等待你們去發掘。不足之處歡迎你們指正。
Ps:此方法參考了網友的文章,須要的可參考: