2016-05-01 260 views
2

我有幾個類名爲Child1,Child2 ...等,從對象父繼承。我需要通過名稱創建一個對象,例如,如果我有字符串「Child1」,我需要創建對象Child1等等。對象構造函數的C++數組

我想過是這樣的:

struct registry_entry { 
    const char* name; 
    IREGISTRY* (*initializer)(); 
}; 

struct registry_entry registry_list[] = 
{ 
    {"xml", &REGISTRY_XML::REGISTRY_XML}, 
} 

但我不能讓對象constructor.I的地址相信這個問題一定已經解決了,解決的辦法是很簡單,但我不能找到它。

+0

你可以使用免費的功能或靜態成員函數,而不是構造函數。 – songyuanyao

+0

是的,使用工廠/生成器功能會更簡單,更清潔。 – benzeno

回答

6

構造函數和析構函數是特殊函數,不能通過函數指針訪問。

您需要創建一個靜態成員函數一樣

struct REGISTRY_XML { 
    static IREGISTRY* create(); 
}; 

因此,你可以稱其爲

struct registry_entry registry_list[] = 
{ 
    {"xml", &REGISTRY_XML::create}, 
} 
2

你的代碼看起來類似C的非常不很C++ - 樣,但如果你實際上可以使用C++ 11的全部功能,那麼我會結合使用std::function,lambda,std::unique_ptrstd::map

lambda表達式可以包裝構造沒有你不必編寫單獨的包裝函數,std::function允許將lambda表達式存儲在地圖,std::unique_ptr消除了許多存儲器管理錯誤,並std::map執行從字符串初始化劑功能的實際映射。

下面是一個完整的例子:

#include <functional> 
#include <string> 
#include <memory> 
#include <map> 
#include <iostream> 

struct IREGISTRY { 
    virtual ~IREGISTRY() {} 
    virtual void print() = 0; 
}; 

struct REGISTRY_XML : IREGISTRY { void print() override { std::cout << "XML\n"; } }; 
struct REGISTRY_INI : IREGISTRY { void print() override { std::cout << "INI\n"; } }; 
struct REGISTRY_JSON : IREGISTRY { void print() override { std::cout << "JSON\n"; } }; 

int main() 
{ 
    std::map<std::string, std::function<std::unique_ptr<IREGISTRY>()>> const registry_list = { 
     { "xml", []() { return std::make_unique<REGISTRY_XML>(); } }, 
     { "ini", []() { return std::make_unique<REGISTRY_INI>(); } }, 
     { "json", []() { return std::make_unique<REGISTRY_JSON>(); } }, 
    }; 

    auto const initializer_iter = registry_list.find("xml"); 
    if (initializer_iter != registry_list.end()) 
    { 
     auto const initializer = initializer_iter->second; 
     auto const registry_ptr = initializer(); 
     registry_ptr->print(); 
    } 
} 
+0

不幸的是我不能使用C++ 11,只有C++ 03標準。所以我不能使用lambdas(我的項目沒有提升,我不想包含它) – Lobster