5

boost::ptr_map抽象基本クラス(例:VectorWrapperBase )を値として格納するがあります。これにより、文字列をさまざまなタイプのベクトルにマップできます。

boost::ptr_map<std::string, VectorWrapperBase> memory_map;
//...
memory_map.insert(str_key, new VectorWrapper<T>());

これは機能しているようです。ただし、memory_map別のクラスのメンバーとしてそのクラスをに格納しようとするとstd::map、コンパイルが失敗します。

class AgentMemory {
  //...
  private:
    boost::ptr_map<std::string, VectorWrapperBase> memory_map;
};

std::map<std::string, AgentMemory> agent_map;
//...
agent_map.insert(std::pair<std::string, AgentMemory>(agent_name, AgentMemory()));

最後の行は次のように失敗します:

/SOMEPATH/boost_1_48_0/boost/ptr_container/clone_allocator.hpp:34
   error: cannot allocate an object of abstract type ‘xyz::VectorWrapperBase’

C ++は初めてなので、これは困惑します。

エラーは、オブジェクトの複製を含むマップ挿入に起因していると思われます。また、オブジェクトは複製できないため、エラーが発生します。AgentMemoryptr_mapVectorWrapper

私の質問は次のとおりです。

  • なぜエラーが発生するのですか?(私の疑いは実際に起こっていることにさえ近いですか?)
  • これに対処するにはどうすればよいですか?

コンパイルエラーに対処するために、私は次のことを検討しましたが、C ++の経験があまりないため、どちらがより適切かを判断できません。

  1. 純粋な指定子(= 0)を削除して、VectorWrapperBase抽象的ではなくなった
    • VectorWrapperBaseインスタンス化されるべきではないため、これはハックのように感じます
  2. VectorWrappersをクローン可能にする
    • これは機能しているようですが、私のユースケースでは、空のコンテナのみがトップレベルマップに割り当てられるため、内部のVectorWrappersをptr_map複製する必要はありません。したがって、クローン可能性はコンパイラーをなだめるためだけにあり、実際の使用法を反映していません。
  3. を忘れて、代わりに ptr_mapとを使用してください。std::mapshared_ptr
    • ベクトルラッパーの存続期間をマップの存続期間にリンクさせたいので、このソリューションにはあまり熱心ではありません。shared_ptrまた、非常にマルチスレッド化されたアプリケーションでの広範な使用による潜在的なオーバーヘッドについても少し心配しています(おそらく不必要にそうですか?) 。
4

1 に答える 1

0

ステートメント

agent_map.insert(std::pair<std::string, AgentMemory>(agent_name, AgentMemory()));

は のデフォルト コンストラクタを呼び出し、AgentMemory次に のデフォルト コンストラクタを呼び出しますboost::ptr_map<std::string, VectorWrapperBase>。これは、抽象基本クラス の存在しないコンストラクタを呼び出そうとしますVectorWrapperBase

したがって、ラップまたは継承する型のすべてのコンストラクターがVectorWrapperBase常に具体的な派生クラスを構築する必要があることを確認する必要があります。あなたの場合、オプション 3 (派生クラスへの共有ポインターのマップ) は賢明かもしれませんが、それはコードのより大きなコンテキストに依存します。

于 2012-05-09T12:04:50.920 に答える