2012-05-09 10 views
5

抽象基本クラス(たとえばVectorWrapperBase)を値として格納するboost::ptr_mapがあります。これにより、文字列を異なる型のベクトルにマップすることができます。抽象基本クラスのptr_mapを含むマッピングオブジェクト

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

これは動作するようです。しかし、別のクラスのメンバとしてmemory_mapがあり、そのクラスをstd::mapに格納しようとすると、コンパイルは失敗します。

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

C++に新なので、これは不可解です:

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())); 

最後の行がで失敗します。

I エラーがptr_mapをクローニングすることを含むAgentMemoryオブジェクトをコピーマップ挿入にダウンしている疑いのある。私のVectorWrapperオブジェクトはcloneableではないので、エラーが発生します。

私の質問は以下のとおりです。

  • は、なぜ私はエラーを取得していますか? (私の疑惑は実際に起こっていることに近いですか)
  • 私はこれにどのように対処しますか?

コンパイルエラーに対処するため、私は次のよう考えられてきましたが、C++での多くの経験することなく、より適切であるかを決めることはできません。

  1. 純粋指定子(= 0)を取り外しのでVectorWrapperBaseですもはやVectorWrapperBase
  2. をインスタンス化すべきではありませんので、これはハックのように感じている
    • 抽象VectorWrappersを作ります cloneable
      • This seems to workですが、空のコンテナのみがトップレベルのマップに割り当てられているため、ptr_map内のVectorWrappersを決して複製する必要はありません。したがって、クローン性は、コンパイラを和らげるためだけに存在し、実際の使用を反映しません。
    • ptr_mapを忘れて、std::mapshared_ptr代わりに使用します。
      • 私はベクトルラッパーの寿命をマップの寿命に近づけたいと思っているので、この解決策に熱心ではありません。また、多量のマルチスレッドアプリケーションでのshared_ptrの広範な使用の潜在的なオーバーヘッドについて少し気になります(恐らく不必要にそうです)。
+0

抽象基本クラスに仮想デストラクタがありますか? – TemplateRex

+0

はい、あります。 .. –

答えて

0

声明

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

抽象のために存在しないコンストラクタを呼び出すようにしようと順番にboost::ptr_map<std::string, VectorWrapperBase>のデフォルトコンストラクタを呼び出しますAgentMemoryのデフォルトコンストラクタを呼び出しますベースクラスVectorWrapperBase

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

+0

ありがとうございました。私が混乱しているのは 'ptr_map'が空になって始まり、なぜ' VectorWrapperBase'のコンストラクタを呼び出す必要があるのでしょうか? –

+0

@ShawnChin私が私の答えで説明したように、 'AgentMemory()'引数を持つ 'insert()'呼び出しはコンストラクタ呼び出しを生成します。 – TemplateRex

+0

おそらく私は誤解していましたが、 'VectorWrapperBase'は' AgentMemory'のメンバーではないので、なぜインスタンスを作成するのか分かりません。つまり、 'VectorWrapperBase'は、' ptr_map'がカプセル化クラスのコピーコンストラクタによってコピーされる必要があるため、クローン可能でなければならないという事実に感謝します。 –

関連する問題