反射機制實現C++經過字符串(類名)建立對象

由於前不久須要作一個合併多個項目代碼,因此須要經過配置文件來控制建立對象,百度用字符串建立對象,搜索半天無果,後來翻看大話設計模式的時候在工廠模式看到一個反射機制,即經過類名建立對象,因此搜索了一下,果真可以找到,因此下載之後分析了哈,進行本身需求進行修改,現整理一下。使用qt5.5.1進行編碼。設計模式

1、思路分爲如下幾步:

一、定義一個回調函數,用來建立這個類的實例;定義一個哈希,用於保存類名和建立實例的回調函數;編輯器

二、設計一個單例,用於管理哈希。(可用靜態成員變量替換);函數

三、設計一個工廠類,。經過類工廠來動態建立類對象和註冊類;測試

四、建立註冊類,將回調函數存入哈希裏面,類名字作爲map的key值;編碼

五、定義須要建立對象的類,用於測試。.net

2、  下面我來一步一步的講解具體的實現方法。

一、聲明

首先聲明一個回調函數設計

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:此方法參考了網友的文章,須要的可參考:

http://blog.csdn.net/cen616899547/article/details/9317323

http://blog.csdn.net/scythe666/article/details/51718864

相關文章
相關標籤/搜索