0

ItemBase のすべてのサブクラスである ItemOne、ItemTwo、ItemThree、および ItemFour というクラスのリストがあるとします。

これらのクラスの名前を受け入れる ItemGenerator という別のクラスにコンストラクターが必要です。どうすればいいですか?

ItemGenerator *someItem = new ItemGenerator(ItemThree);

別のオプションは、これらのクラスの 1 つで静的関数を渡すことですが、その方法がわかりません。

ItemGenerator *someItem = new ItemGenerator(ItemOne::start());

ありがとう。

4

7 に答える 7

1

name、つまり文字列を本当に渡しますか? 次に、Item* クラスに対応する関数を提供する必要があります。

class ItemOne {
  static std::string name();
};

ItemGenerator *someItem = new ItemGenerator(ItemThree::name());

それともテンプレートをお探しですか?そこにはさまざまな可能性があります。おそらく ItemGenerator 基本クラスから派生したクラス テンプレートを作成します。

class AbstractItemGenerator { /* ... */ };

template <class Item>
class ItemGenerator {
  ItemGenerator();
};

ItemGeneratorBase *someItem = new ItemGenerator<ItemTwo>();

または、コンストラクターのみをテンプレート化します。パラメーターを明示的に指定することはできないため、引数推定を使用します。

//take 1: use pointers
class ItemGenerator {
  template <class Item>
  ItemGenerator(Item* dummy);
};

ItemGenerator *someItem = new ItemGenerator((ItemFour*)NULL);

//take 2: use a tag struct
template <class I>
struct ItemTag{};

class ItemGenerator {
  template <class Item>
  ItemGenerator(ItemTag<Item> tag);
};

ItemGenerator *someItem = new ItemGenerator(ItemTag<ItemOne>());

これらのいずれかがお客様のニーズに合っているかどうかはわかりません。たぶん、これを何に使いたいかを詳しく説明してください。

于 2013-03-01T16:45:12.427 に答える
1

テンプレートを使用できます:

struct ItemBase {virtual ~ItemBase();};
struct ItemOne : ItemBase {};
struct ItemTwo : ItemBase {};
struct ItemThree : ItemBase {};
struct ItemFour : ItemBase {};

struct ItemGeneratorBase {
    virtual unique_ptr<ItemBase> generate() {}
    virtual ~ItemGeneratorBase() {}
};
template<typename Item>
struct ItemGenerator : ItemGeneratorBase {
    virtual unique_ptr<ItemBase> generate() {
        return unique_ptr<ItemBase>(new Item());
    }
};

std::unique_ptr<ItemGeneratorBase> someItem(new ItemGenerator<ItemThree>());
于 2013-03-01T16:38:27.590 に答える
0

クラスは C++ のオブジェクトではないため、関数はクラスの名前をパラメーターとして受け入れることができません。ただし、テンプレート関数はクラス名でパラメーター化できます。

このようなもの:

template<class T> 
ItemGenerator* ItemGeneratorFactory() { T::start(); ...}

ItemGenerator *someItem = ItemGeneratorFactory<ItemThree>();
于 2013-03-01T16:35:57.910 に答える
0

私は少しさびていますがItemBase、コンストラクターを入れるだけですべてのサブクラスを受け入れることができると確信しています。

ItemGenerator::ItemGenerator(ItemBase base){\\do something with base
}

または、それとテンプレートの使用が機能しない場合は、複数のコンストラクターを作成できます。

ItemGenerator::ItemGenerator(ItemOne one){}
ItemGenerator::ItemGenerator(ItemTwo two){}
...
于 2013-03-01T16:44:33.683 に答える
0

他の回答が示すように、テンプレートを使用して達成できます。

別のアイデアを提供するために、必要なもの(またはそのクラスでやりたいこと)のインスタンスを作成する関数ポインターを渡すことができます

ItemGenerator(ItemClassPtr itemClassFn)
{
    void * myObject = itemClassFn();
}
于 2013-03-01T16:42:59.137 に答える
0

これはまさにFactory デザイン パターンが行うことです。基本的に、ItemGenerator クラスには、ItemBase オブジェクトへのポインターを返すことができる静的メソッドがありますが、静的メソッドへのパラメーターに応じて、Item1、Item2 などへのポインターを返すことができます。

たとえば、ItemGenerator クラスでは、

static ItemBase *Generate( <any parameter> )
{
    switch (parameter)
    {
        case Value1: return new Item1();
        ...
        ...
     }
 }
于 2013-03-01T16:45:20.303 に答える
0

の目的を知らずに問題の解決策を見つけることは困難ですItemGenerator

Mankarse が言うように、1 つの解決策は、テンプレートを使用してクラスをジェネレーターに渡すことです。

それでも、ItemGeneratorテンプレート化できない場合、またはここでテンプレートを使用したくない場合でも、std::function または boost::function のいずれかを使用して、提案どおりに関数を渡すことができます。

C++ にリフレクションを追加するのに役立つライブラリもいくつかあります。CAMPのことは覚えていますが、まだ活動しているかどうかはわかりません。そこにあなたの問題の解決策が見つかるかもしれません。

于 2013-03-01T18:53:53.557 に答える