C ++ STLコンテナのポリモーフィズム

ジャック

この問題に対してエレガントな解決策が存在するかどうか疑問に思いました。

次のように仮定します。

class Base {
  private:
    int data;
  protected:
    Base(int data) : data(data) { }
    int getData() const { return data; }
    virtual bool someOp() = 0;
}

class Derived1 : public Base {
  private:
    int data2;
  public:
    Derived1(int data, int data2) : Base(data), data2(data2) { }
    int getData2() const { return data2; }
    bool someOp() override { /* something */ }
}

class Derived2 : public Base {
  private:
    float data2;
  public:
    Derived1(int data, float data2) : Base(data), data2(data2) { }
    float getData2() const { return data2; }
    bool someOp() override { /* something */ }
}

そして、階層を完全に制御できるので、階層BaseDerivedXクラスも拡張されないと想定できます。

今、私はそれらをに保存しstd::vectorたいと思います。ポリモーフィズムを使用したい場合、ポインターを保存する必要があります。そうしないと、オブジェクトのスライスによって追加の派生プロパティを保存できなくなります。だから私は基本的にを使用することを余儀なくされていますstd::vector<unique_ptr<Base>>

しかし、これらのオブジェクトをたくさん格納する必要があり、ダブルヒープ割り当て(内部std::vector+オブジェクト自体)に無駄にしたくないと仮定しましょう。同時に、次のことを仮定できます。

  • クラス階層は完全に定義されており、知らないうちに拡張されることはありません。
  • sizeof(DerivedX) より大きくなることはありません sizeof(Base)

したがって、ポリモーフィズムを維持し、ポインターの格納を回避するためのエレガントな方法があるかどうか疑問に思っています。私は次のようないくつかの解決策を考えることができます

class Base {
  enum {
   DERIVED1,
   DERIVED2
  } type;

  int data;
  union {
    int derived1data;
    float derived2data;
  }

  bool someOp() {
    if (this->type == DERIVED1) ...
    else if ..
  }
}

しかし、これは明らかにエレガントではありません。sizeof(Derived) == sizeof(Base)保護されたユニオンを使用し、BaseそこからアクセスしてDerived、アドレスをstd::vector目的のタイプの要素にキャストすることで、オブジェクトのスライスが発生しないという事実を利用することもできますが(列挙型による)、これも醜いようです。

Yakk-Adam Nevraumont

型消去と小さなバッファーの最適化。

C ++のほとんどすべてのプロパティを消去と入力して、プロパティを現在不明な型に適用する方法を「知っている」カスタムインターフェイスを作成できます。

boost::anytypeは、コピー、破棄、typeidの取得、および完全に一致するtypeへのキャストバックのために消去されます。std::functionタイプは消去してコピーし、特定の署名で呼び出し、破棄し、同一タイプにキャストバックします(最後のものはめったに使用されません)。

無料のストアベースの型消去実装は、ポインタを交換することにより、「無料で」移動セマンティクスを取得します。

あなたの場合、そのタイプに「十分な大きさ」の整列されたストレージを作成する必要があります。コピー、ベースへの参照として取得、破棄、そしておそらく移動するには、erase downと入力する必要があります(内部に保存しているため)。

std::aligned_storageあなたのタスクを対象としています(保存しようとしているすべてのタイプの配置要件を渡すことができます)。次に、新しいオブジェクトをインプレースします。

void*コピー、移動、破棄、および変換を介して、オブジェクトに対して実行する操作のテーブルを作成しますbase*

template<class Sig>using f = Sig*;

struct table {
  f<base*(void*)>             convert_to_base;
  f<base const*(void const*)> convert_to_const_base;
  f<void(void*,void const*)>  copy_construct;
  f<void(void*)>              destroy;
  f<void(void*,void*)>        move_construct;
};
template<class T>
table const* get_table() {
  static table t = {
    // convert to base:
    [](void*p)->base*{
      T*t=static_cast<T*>(p);
      return t;
    },
    // convert to const base:
    [](void const*p)->base const*{
      T const*t=static_cast<T const*>(p);
      return t;
    },
    // etc
  };
  return &t;
}

今保存するget_table<T>()(それは手動で実装、基本的に仮想関数テーブルである)あなたのタイプ消去されたインスタンスでは、との関数を使用するようにラッピング定期的なクラスを作成table、操作しますaligned_storage<?...>

さて、これはを使用するか、ヒープストレージを使用せずにのように動作するboost::variantタイプのようなものを介して簡単に行うことができますany一部のリンクには、上記の疑似仮想関数テーブル手法をコンパイルする実装が含まれています。整列ストレージを間違って使用した可能性がありますが、注意してください。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

C ++ stdコンテナ-ポインタのないポリモーフィズム。出来ますか?

分類Dev

C ++のポリモーフィズム

分類Dev

C#のポリモーフィズムのコピーコンストラクター

分類Dev

C ++のポリモーフィズムと私の試験

分類Dev

C#での動的ポリモーフィズムの例

分類Dev

C ++デザインとポリモーフィズム

分類Dev

C ++の静的ポリモーフィズム

分類Dev

C ++:演算子の動的ポリモーフィズム

分類Dev

C ++の継承とポリモーフィズム

分類Dev

C#の静的および動的ポリモーフィズム

分類Dev

C ++の継承とポリモーフィズム

分類Dev

Objective-Cのポリモーフィズム-iOS

分類Dev

C#での継承とポリモーフィズム

分類Dev

C ++ RAIIとポリモーフィズムの互換性

分類Dev

ポリモーフィズムC ++の誤解

分類Dev

C ++のポリモーフィズム(予期しない動作)

分類Dev

簡単な例でのC ++ポリモーフィズム

分類Dev

C ++テンプレート、ポリモーフィズム、およびテンプレート共分散

分類Dev

c ++-メモリリークとポリモーフィズム

分類Dev

動的コンテナのC ++ STLでのメモリ割り当て

分類Dev

C ++インターフェース、継承、ポリモーフィズム

分類Dev

vtableのc ++アイデアのポリモーフィズム(動的バインディング)

分類Dev

C ++ファンクターポリモーフィズムを理解する

分類Dev

セット<T>対セット<T、コンパレータ>(C ++ポリモーフィズム)

分類Dev

C ++ポリモーフィズムは子コンストラクターを使用します

分類Dev

一緒に使用されるC ++テンプレートポリモーフィズム

分類Dev

C ++のポリモーフィズム-ポインタを介したアクセス関数

分類Dev

ポリモーフィズムとC ++のクラステンプレートからのメソッドのオーバーライド

分類Dev

CのOOポリモーフィズム、エイリアシングの問題?

Related 関連記事

  1. 1

    C ++ stdコンテナ-ポインタのないポリモーフィズム。出来ますか?

  2. 2

    C ++のポリモーフィズム

  3. 3

    C#のポリモーフィズムのコピーコンストラクター

  4. 4

    C ++のポリモーフィズムと私の試験

  5. 5

    C#での動的ポリモーフィズムの例

  6. 6

    C ++デザインとポリモーフィズム

  7. 7

    C ++の静的ポリモーフィズム

  8. 8

    C ++:演算子の動的ポリモーフィズム

  9. 9

    C ++の継承とポリモーフィズム

  10. 10

    C#の静的および動的ポリモーフィズム

  11. 11

    C ++の継承とポリモーフィズム

  12. 12

    Objective-Cのポリモーフィズム-iOS

  13. 13

    C#での継承とポリモーフィズム

  14. 14

    C ++ RAIIとポリモーフィズムの互換性

  15. 15

    ポリモーフィズムC ++の誤解

  16. 16

    C ++のポリモーフィズム(予期しない動作)

  17. 17

    簡単な例でのC ++ポリモーフィズム

  18. 18

    C ++テンプレート、ポリモーフィズム、およびテンプレート共分散

  19. 19

    c ++-メモリリークとポリモーフィズム

  20. 20

    動的コンテナのC ++ STLでのメモリ割り当て

  21. 21

    C ++インターフェース、継承、ポリモーフィズム

  22. 22

    vtableのc ++アイデアのポリモーフィズム(動的バインディング)

  23. 23

    C ++ファンクターポリモーフィズムを理解する

  24. 24

    セット<T>対セット<T、コンパレータ>(C ++ポリモーフィズム)

  25. 25

    C ++ポリモーフィズムは子コンストラクターを使用します

  26. 26

    一緒に使用されるC ++テンプレートポリモーフィズム

  27. 27

    C ++のポリモーフィズム-ポインタを介したアクセス関数

  28. 28

    ポリモーフィズムとC ++のクラステンプレートからのメソッドのオーバーライド

  29. 29

    CのOOポリモーフィズム、エイリアシングの問題?

ホットタグ

アーカイブ