0

次の Java の概念を C++ に移植する必要があります。

オブジェクト ID キーとクラス タイプ値を保持するハッシュ マップ:

 Map<String, Class> _objectsBank = new HashMap<>();

init メソッドのどこかで、次のようにバンクを埋めます。

    _objectsBank .put("CLASS_ID_1", MyClass1.class);
    _objectsBank .put("CLASS_ID_2", MyClass2.class);
    ....

その後、必要に応じてそのバンクに保存されたクラスの 1 つのインスタンスを作成します。「怠惰な」初期化の種類:

 private MyClass initNewProg(String name) {

    MyClass instance;


    try {

        Class cl = _objectsBank.get(name);
        java.lang.reflect.Constructor co = cl.getConstructor(String.class);
        instance= (MyClass) co.newInstance(name);
        return instance;

    } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
    {
        e.printStackTrace();
        return null;
    }
 }

C++ でどのように行うのですか? クラス型を std::map 値として設定して、後でクエリを実行して適切なインスタンスを構築できるようにするにはどうすればよいですか? Boostライブラリにこのようなものはありますか?

4

4 に答える 4

5

関数ポインタを使用できます。コンストラクターへの関数ポインターを取得できないため、ファクトリー関数を使用する必要があります。

template <class Derived>
Base* create()
{
        return new Derived;
}

次に、マップ内のファクトリ関数のテンプレート インスタンスへの関数ポインターを保存して、派生クラスを構築できます。

int main()
{
        std::map<std::string, Base*(*)()> classMap;
        classMap["Derived1"] = &create<Derived1>;
        classMap["Derived2"] = &create<Derived2>;

        delete classMap["Derived1"]();
        delete classMap["Derived2"]();   
}

イデオネで見る

于 2013-01-27T15:26:08.210 に答える
3

クラス名を保持している文字列からオブジェクトをインスタンス化する方法はありますか? を見てください。ファクトリ パターンを使用して名前でクラスをインスタンス化します。これは、問題と、それぞれの長所と短所を含む複数のアプローチを説明します。例では、クラスのコンストラクターの登録について説明します。これにより、@Karthik T のソリューションで言及した複数の if ステートメントの問題が解決されます。

于 2013-01-27T15:33:51.987 に答える
1

1 つのオプションは、クラス名の代わりにインスタンスを表す文字列を格納し、後でファクトリ メソッドを使用して正しいインスタンスを返すことです。ただし、以下を実行して反射プロセスを手動で模倣する必要があるため、これは扱いにくいものになります。

MyClass* initNewProg(string name) {
    if(name == "derived1")
       return new Derived1();
    else if(name == "derived2")
    ....
}

もう 1 つの方法は、個々のファクトリ メソッドと関数ポインターを使用することです。

typedef MyClass* (*MyFactoryFunc)();

map<string,MyFactoryFunc> myMap;

MyClass* createDerived1(){return new Derived1();}
...

MyClass* initNewProg(string name) {
    return myMap[name]();
}
于 2013-01-27T14:31:33.147 に答える
0

Qt を使用してオブジェクトを QObjects にするオプションがある場合は、Qt メタオブジェクト システムを介してこれを行うことができます。それを調べるための実際的な出発点はQObject::metaObject()QMetaObject::newInstance()メソッドのドキュメントです。

これは、C++ でこのような機能を取得するには、多かれ少なかれ Qt などの追加の前処理ステップが必要mocであり、これをサポートするための追加のメソッドとデータを含む追加の .cpp ファイルを作成するという点も示しています。

より軽量なオプションは、独自の単純なプリプロセッサを開発することです。たとえば、.cpp ファイル内の特別なコメント表記を読み取り、オブジェクト タイプを関数にマップしてオブジェクトをインスタンス化するマップなどを作成するコードを生成します。 . ほとんどの作業を C++ テンプレート システムに任せられるかどうかはわかりません。

于 2013-01-27T14:38:56.677 に答える