反射機制實現C++通過字符串(類名)創建對象。本站提示廣大學習愛好者:(反射機制實現C++通過字符串(類名)創建對象)文章只能為提供參考,不一定能成為您想要的結果。以下是反射機制實現C++通過字符串(類名)創建對象正文
因為前不久需要做一個合並多個項目代碼,所以需要通過配置文件來控制創建對象,百度用字符串創建對象,搜索半天無果,後來翻看大話設計模式的時候在工廠模式看到一個反射機制,即通過類名創建對象,所以搜索了一下,果然能夠找到,所以下載以後分析了哈,進行自己需求進行修改,現整理一下。使用qt5.5.1進行編碼。
一、思路分為以下幾步:1、定義一個回調函數,用來創建這個類的實例;定義一個哈希,用於保存類名和創建實例的回調函數;
2、設計一個單例,用於管理哈希。(可用靜態成員變量替換);
3、設計一個工廠類,。通過類工廠來動態創建類對象和注冊類;
4、創建注冊類,將回調函數存入哈希裡面,類名字做為map的key值;
5、定義需要創建對象的類,用於測試。
二、 下面我來一步一步的講解具體的實現方法。 1、聲明首先聲明一個回調函數
typedef void* (*fun_ptr)();
聲明一個哈希:
typedef std::map<const QString, fun_ptr> create_obj_map; //用來保存回調函數指針,通過registClass()函數來實現類名和函數的插入。
2、定義單例
定義一個單例,用於處理哈希,也可以定義成一個靜態成員變量,但是之前試過幾次,沒成功,先使用單例吧。
class LazySingleton
{
public:
template<class T>
static T& instance()
{
static T _instance;
return _instance;
}
};
3、定義工廠類定義一個工廠類,用於通過此獲取哈希,方法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));
}
這樣,我們的單例工廠類就設計完成了。
4、添加注冊類下面我們需要設計一個用來動態創建類的類,被創建的類通過本類來向類工廠注冊對象的函數。
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);來進行類注冊,後面再來考慮吧),參數,第一個是類名,第二個是新類的創建對象的函數。到這一步,類反射的功能即將要實現了。
5、添加被創建的類下面我們來設計最後一個類,就是將要被動態創建的類,先帖碼。
class Foo
{
public:
Foo()
{
_id = 1;
_name = "Foo";
}
public:
int _id;
std::string _name;
};
REGISTER(Foo);
Foo類是我們要動態創建出來的類。REGISTER(Foo)用於把類foo進行宏替換後生成一個新類,用於創建foo的對象的。
6、測試
到此,所有的准備工作都做好了,接下來就是測試了。
在main中添加代碼:
Foo* foo = static_cast<Foo*>(ClassFactory::getInstance("Foo"));
std::cout << foo->_name << std::endl;
當界面上打印輸出Foo的時候,就證明是成功了。
7、總結
到此,C++反射的實現講解完成,這類實現方法適合在開發各類的編輯器中去使用,包括微軟的MFC等等。在開發編輯器的階段,並沒有相應的類,但是使用者想通過在編輯器中傳入類的名字,然後在開發中,根據編輯器傳入的類名,新建一個類去實現的話,這種方法非常適用,更多的用法等待大家去發掘。不足之處歡迎大家指正。
Ps:此方法參考了網友的文章,需要的可參考:
http://blog.csdn.net/cen616899547/article/details/9317323
http://blog.csdn.net/scythe666/article/details/51718864