2011-11-25 10 views
5

可能性の重複:C++で
Is there a way to instantiate objects from a string holding their class name?名前だけを知っているオブジェクトをどのようにインスタンス化できますか?

、私は、ユーザーが実行時に作成されるオブジェクトタイプの名前を入力したい、そして、私が得る文字列に応じて、それらから、プログラムは正しいオブジェクトをインスタンス化します(要するに、私はファクトリメソッドパターンを実装しています)。ただし、プログラムが新しいオブジェクト型をサポートする必要がある場合、既存のコードを変更することはできません。

したがって、if ... else if ... else if ... stuffをメソッドから削除しても、自分のプログラムが特定の製品タイプの正しいオブジェクトをインスタンス化するようにすることができます(多くのうち、コンパイル時にのみ知られています)?

私の周りを検索すると私にこのリンクがあります:Is there a way to instantiate objects from a string holding their class name?それは私が望むものだと思われますが、コードを全く理解できません。

本当にありがとうございます。

+0

@CharlesB反射は必要ありません。工場を使うことができます。 –

+1

@LuchianGrigore:ファクトリはデザインパターンです。リフレクションは言語機能です。 if..else..elseなしで動作するファクトリが必要な場合は、リフレクションを持つ言語、またはAlessandroの答えのようなバイナリ・プラグイン・アーキテクチャが必要です – CharlesB

答えて

5

必要なすべてのクラスがいくつかの共通の基本クラスから派生している、とあなたが働くことができますが、あなたが一般的にベース・インタフェースを(使用に限定される場合にのみ動作しますその周りにいくつかの追加の努力)。

// Immutable core code: 

#include <map> 
#include <string> 

class Base 
{ 
    typedef Base * (*crfnptr)(const std::string &); 
    typedef std::map<std::string, crfnptr> CreatorMap; 

    static CreatorMap creators; 

public: 
    virtual ~Base() { } 
    Base * clone() const { return new Base(*this); } 

    static Base * create_from_string(std::string name) 
    { 
    CreatorMap::const_iterator it = creators.find(name); 
    return it == creators.end() ? NULL : it->first(); 
    } 

    static void register(std::string name, crfnptr f) 
    { 
    creators[name] = f; 
    } 
}; 

は今、あなたはあなたの新しいコードから新しい派生クラスを追加することができます:

// your code: 

#include "immutable_core.hpp" 

class Foo : public Base 
{ 
public: 
    Foo * clone() const { return new Foo(*this); } 
    static Foo * create() { return new Foo; } 
}; 

Base::register("Foo", &Foo::create); 

が、あなたは単にBase * p = Base::create_from_string("Foo");を呼び出して、クラスを作成するためにここに一つの方法です。

+0

ここで 'clone()'関数が必要ですか? それらを取り除くことは良い考えであるかどうかわかりません。 – Daan

+0

@Daan:あなたはそうです、彼らは工場自体のために必要ではありませんが、オブジェクトの最も派生した型を知らない状況でコピーコンストラクタの役割を担うので、テーマに関連しています。 –

+0

もし私が正しく理解すれば、無意識のうちに 'Base *'から 'Derived *'にキャストする必要がありますか? – Daan

2

これは、プラグインシステムのようなものを実装することができます。私はこれをLinuxでdlopenで実装しました。プログラムを変更する必要はありませんが、実行時にロードされる動的ライブラリとして新しいクラスを追加するだけで済みます。

あなたはより多くの情報のためにここに開始することができます:C++ dlopen mini HOWTO