5

いくつかのサブクラスを持つ C++ の抽象クラスがあります。

どういうわけか、マクロまたはテンプレートのメタプログラミングによって、そのようなことを行うことができますか:

foreach subclass of Base:
  mymap[subclass::SOME_CONSTANT] = new subclass();
4

2 に答える 2

7

いいえ、あなたがすることはできません。

どうやら、あなたが望むのはFactory(またはおそらくAbstract Factory) です。

C++ では、Factory クラスをセットアップし、ビルダーを登録します。

class FooFactory
{
public:
  typedef std::function<Foo*()> Builder;

  /// returns true if the registration succeeded, false otherwise
  bool Register(std::string const& key, Builder const& builder) {
    return map.insert(std::make_pair(key, builder)).second;
  }

  /// returns a pointer to a new instance of Foo (or a derived class)
  /// if the key was found, 0 otherwise
  Foo* Build(std::string const& key) const {
    auto it = _map.find(key);
    if (it == _map.end()) { return 0; } // no such key
    return (it->second)();
  }

private:
  std::map<std::string, Builder> _map;
};

このファクトリのシングルトンを作成して、ライブラリのロード中に派生クラスを登録できます。これは、プラグインのようなアーキテクチャに便利です。

FooFactory& GetFooFactory() { static FooFactory F; return F; }

また、便利なビルダーを準備できます。

template <typename Derived>
Foo* fooBuilder() { return new Derived(); }

次に、派生クラスをファクトリに登録することが期待されます。

static const bool registeredBar =
    GetFooFactory().Register("Bar", fooBuilder<Bar>);

注: ファクトリがシングルトンであることは必須ではありませんが、ライブラリのロードが終了すると一定であるため、ここではそれほど悪くはありません。

注: 適切なプラグイン アーキテクチャでは、ライブラリのアンロード時に登録解除を処理するために、(bool の代わりに) RAII を使用する必要があります。しかし、それははるかにまれです。

于 2011-03-27T17:53:38.213 に答える
0

C++ では、型の反復処理は許可されていません。また、列挙メンバーの列挙はできません。これを参照してください:

enum Color
{
    red,
    green,
    blue=5,
    yellow
};

さらに、C++ コンパイラはコンパイル ユニットを独立してコンパイルします。基本クラスの実装をコンパイルするときに、クラスが継承される場合があることを認識できないことがイメージできます。

于 2011-03-27T17:55:58.323 に答える