2016-05-01 10 views
2

オブジェクトParentから継承した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(); 
}; 

のような静的メンバ関数を作成する必要があるので、あなたはあなたのコードは非常にC++に非常に C様およびないに見える

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

としてそれを参照することができます - のように、実際にC++ 11のフルパワーを使用できるのであれば、std::function、lambdas、std::unique_ptrおよびstd::mapの組み合わせを使用します。

ラムダはstd::functionあなたは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標準しか使用できません。だから私はラムダを使用することはできません(私は私のプロジェクトでは後押しがなく、私はそれを含めたくありません) – Lobster