方法:将对插入到multimap中,其中一种类型是抽象的?

时间:2011-11-04 17:12:08

标签: c++ stl map polymorphism abstract-class

例如:

abstract class goal
class priority
class childgoal

multimap<priority, goal> mm;
mm.insert(make_pair(priority(), childgoal());

我收到错误:

cannot declare field 'std::pair<priority, goal>::second'
to be of abstract type 'goal'

如果我没记错的话,在使用之前,Pair使用默认构造函数创建第二个,这是遇险的原因。我可能不正确,但它可以解释错误。

我如何解决这个问题...当其中一种类型是抽象的时候,我怎样才能完成插入多图(或者可能是地图)?

3 个答案:

答案 0 :(得分:4)

你可以制作一个指针图:

#include <memory>
#include <map>

class Base { };
class Derived1 : public Base { };
class Derived2 : public Base { };

typedef std::shared_ptr<Base> MyPtr;
typedef std::multimap<Key, MyPtr> MyMap;

int main()
{
  MyMap m { { Key(1), MyPtr(new Derived1) }, { Key(2), MyPtr(new Derived2) } };
}

统一初始化语法需要C ++ 11支持。在旧版本中,您可以插入:

m.insert(MyMap::value_type(Key(1), MyPtr(new Derived1)));

如果没有其他人需要映射对象,您可能会改为使用std::unique_ptr<Base>。一个简单的改变typedef的问题。

答案 1 :(得分:1)

你显然想要使用多态(因为你想把派生类放在一个只有基类的预期)。

但是每次你想要使用多态时,你都应该使用指针到基类的自动化(如果我没记错的话,引用到基础也有效)。假设childgoal公开继承目标,则以下陈述为真:

  • childgoal 目标
  • 指向目标的指针可指向目标 childgoal (或任何派生类)
  • 目标实例是-NOT-a childgoal

所以基本上,如果你能够将你的childgoal转换为一个目标(,因为你试图实例化一个抽象类,这是不可能的),你将摆脱所有的额外成员存在于儿童中,从而失去原始物体。我认为这不是你的意图。

如果您担心经典指针会出现内存管理问题,可以考虑在此处使用shared_pointers:

abstract class goal;
class priority;
class childgoal : public goal;

typedef std::tr1::shared_ptr<goal> goalPtr; //sadly I think std::tr1 is not a multiplatform namespace 

multimap<priority, goalPtr> mm;
goalPtr tmpChildGoal(new childgoal()); //always use named shared pointer !
mm.insert(make_pair(priority(), tmpChildGoal);

答案 2 :(得分:0)

非常简单地说: 抽象类只能用作指针或引用。 如果你需要一个类的多态实例的容器,你需要存储一个指针,或者更好的是,一个智能指针,可能是unique_ptr。