映射包含抽象基类的ptr_map的对象

Sha*_*hin 5 c++ abstract-class stdmap boost-ptr-container

我有一个boost::ptr_map存储抽象基类(例如VectorWrapperBase)作为值,这允许我将字符串映射到不同类型的向量.

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

这似乎有效.但是,当我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()));
Run Code Online (Sandbox Code Playgroud)

最后一行失败了:

/SOMEPATH/boost_1_48_0/boost/ptr_container/clone_allocator.hpp:34
   error: cannot allocate an object of abstract type ‘xyz::VectorWrapperBase’
Run Code Online (Sandbox Code Playgroud)

作为C++的新手,这是令人费解的.

怀疑错误是由于地图插入复制了AgentMemory涉及克隆的对象ptr_map.由于我的VectorWrapper对象不可复制,因此会引发错误.

我的问题是:

  • 为什么我收到错误?(我的怀疑是否接近实际发生的事情?)
  • 我该如何解决这个问题?

为了解决编译错误,我考虑了以下内容,但是没有太多C++经验无法确定哪个更合适:

  1. 删除纯说明符(= 0),因此VectorWrapperBase不再是抽象的
    • 这感觉就像一个黑客,因为VectorWrapperBase永远不应该被实例化
  2. 使VectorWrappers 可以复制
    • 这似乎有效,但在我的用例中,只有空容器被分配给顶层映射,因此内部的VectorWrappers ptr_map永远不会被克隆.因此,克隆性只是为了安抚编译器而不反映实际用法.
  3. 忘记ptr_map并使用一个std::mapshared_ptr不是.
    • 我不太热衷于这个解决方案,因为我希望矢量包装器的生命周期与地图的生命周期相关联.关于shared_ptr在大量多线程应用程序中广泛使用的潜在开销,我也有点担心(可能是不必要的?).

Tem*_*Rex 0

该声明

agent_map.insert(std::pair<std::string, AgentMemory>(agent_name, AgentMemory()));
Run Code Online (Sandbox Code Playgroud)

将调用 的默认构造函数AgentMemory,后者又将调用 的默认构造函数boost::ptr_map<std::string, VectorWrapperBase>,后者将尝试调用抽象基类的不存在的构造函数VectorWrapperBase

因此,您必须确保每个包装或继承类型的构造函数VectorWrapperBase都应始终构造一个具体的派生类。在您的情况下,选项 3(指向派生类的共享指针的映射)可能是明智的,但这取决于代码的更大上下文。