6

後で取得する必要があるさまざまなデータ型メンバーを運ぶ派生クラス型を受け入れるC++のインターフェイスを提供する最も洗練された方法は何ですか。以下の例は、ContainerクラスがBaseItemの派生バリアントの一種であるItemを「投稿」するメソッドを提供する場合にこれを示しています。後で、派生アイテムを取り戻し、その値を抽出したいと思います。

私が望んでいる主なことは、Containerインターフェース(postとreceive)が将来同じままでありながら、さまざまな「Item」派生型を定義して「渡す」ことを可能にすることです。どういうわけか、これにはテンプレートの方が適しているでしょうか。RTTIは使いたくないです。これには単純でエレガントな答えがあるかもしれませんが、今はそれについて考えるのに苦労しています。

class ItemBase {
  // common methods
};

class ItemInt : public ItemBase
{
  private:
    int dat;
  public:
    int get() { return dat; }  
};

class ItemDouble : public ItemBase
{
  private:
    double dat;
  public:
    double get() { return dat; }  
};

class Container {
 public:
   void post(int postHandle, ItemBase *e);      
   ItemBase* receive(int handle); // Returns the associated Item
};

int main()
{
   ItemInt *ii = new IntItem(5);
   Container c;
   c.post(1, ii);

   ItemInt *jj = c.receive(1); 
   int val = jj->get();  // want the value 5 out of the IntItem
}
4

4 に答える 4

5

これは間違いなく、継承ではなくジェネリック プログラミングの候補です。ジェネリック (テンプレート) は、異なるデータ型に対して同一の処理が必要な場合に理想的です。ItemInt および ItemDouble クラスは、オブジェクト指向の設計原則に違反しています (get() メソッドは、実際のサブタイプに応じて異なるデータ型を返します)。汎用プログラミングはそのために構築されています。他の唯一の答えはタグ付きのデータ型であり、私は個人的にペストのようなものを避けています.

于 2012-01-04T21:52:02.207 に答える
1

どうですか?

template<typename T>
class Item
{
  private:
    T dat;
  public:
    T get() { return dat; }  
};

class Container {
 public:
   template<typename T>
   void post(int postHandle, Item<T> *e);      

   template<typename T>
   Item<T>* receive(int handle); // Returns the associated Item
};

int main()
{
   Item<int> *ii = new Item<int>(5);
   Container c;
   c.post(1, ii);

   Item<int> *jj = c.receive<int>(1); 
   int val = jj->get();  // want the value 5 out of the IntItem
}
于 2012-01-04T22:20:37.357 に答える
0

純粋なテンプレート アプローチは機能しません。なぜなら、明らかにコンテナーに混合型を入れたいからです。any実際のものを復元する必要があると思いますが、ブーストのようなもので作業できます。この場合に求められるのは、型に依存しないメソッドと仮想メソッドを公開する基本クラスと、実際のアイテムを保持するためのテンプレート化された派生クラスです。

class Base {
public:
    virtual ~Base() {}
    virtual void post() = 0;
};

template <typename T>
class Item: public Base {
public:
    Item(T const& value): value_(value) {}
    void post() { std::cout << "posting " << this->value_ << "\n"; }
private:
    T value_;
};

Itemこのアプローチにより、別の値型の派生クラスを作成する必要がなくなります。これらの獣の作成を容易にするために、おそらく適切な作成関数も作成する必要があります。

template <typename T>
std::unique_ptr<Base> make_item(T const& value) {
    return std::unique_ptr<Base>(new Item<T>(value));
}

割り当てられたオブジェクトが解放されたことを確認するためにAstd::unique_ptr<Base>が返されます (C++2011 を使用しない場合は、std::auto_ptr<T>代わりに使用できます)。std::shared_ptr<Base>この型は、コンテナに入れるのにより適した など、他のポインタ型に簡単に変換できます。

于 2012-01-04T23:48:03.103 に答える
0

Container クラスが std::map のように疑わしく見えます。あなたの ItemBase クラスは、ユニバーサル基本クラスである「オブジェクト」の単なる別の名前のように見えます。これは、void* と大差ない (または優れている) と思います。単一のコンテナーに異なるタイプのアイテムを入れようとすることは避けたいと思います。あなたのデザインがそうする必要があると思われる場合は、あなたのデザインを再考します.

于 2012-01-04T22:17:25.493 に答える