程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 反射機制實現C++通過字符串(類名)創建對象

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

編輯:關於C++

反射機制實現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

 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved