你能创建一个继承类的std :: map吗?

时间:2011-12-25 01:19:44

标签: c++ inheritance stdmap

我想知道是否可以创建一个继承类指针的映射。以下是我正在尝试做的一个例子:

#include <string>
#include <map>

using namespace std;

class BaseClass
{
    string s;
};

class Derived1 : public BaseClass
{
    int i;
};

class Derived2 : public Derived1
{
    float f;
};

// Here's what I was trying, but isn't working
template<class myClass>
map<string, myClass>m;

int main()
{
    // Add BaseClasses, Derived1's, and/or Derived2's to m here
    return 0;
}

我得到的错误是:

main.cpp(23): error C2133: 'm' : unknown size
main.cpp(23): error C2998: 'std::map<std::string,myClass>m' : cannot be a template definition

我明白为什么我会收到此错误,但我想知道是否可以创建一个可以容纳不同级别的继承类的地图?如果没有,是否有可能创建一种可以容纳各种类型的管理系统?或者我是否必须制作不同的地图/矢量/数组/等。对于每种类型的课程?

4 个答案:

答案 0 :(得分:3)

是的,您可以在地图中存储继承的类,但指向它们的指针,而不是对象本身。这是一个简短的例子(缺少对指针的内存管理)

#include <iostream>
#include <string>
#include <map>
#include <utility>

using namespace std;

class BaseClass
{
    string s;
public: 
    BaseClass() { s = "BaseClass";} 
    virtual void print() 
    {
        cout << s << std::endl;
    }
};

class Derived1 : public BaseClass
{
    int i;
public:
    Derived1() { i = 10; }
    void print() 
    {
        cout << i << std::endl;
    }

};

class Derived2 : public Derived1
{
    float f;
public:
    Derived2() { f = 4.3;}
    void print() 
    {
        cout << f << std::endl;
    }
};

int main()
{
    map<string, BaseClass*>m;
    m.insert(make_pair("base", new BaseClass()));
    m.insert(make_pair("d1", new Derived1()));
    m.insert(make_pair("d2", new Derived2()));
    m["base"]->print();
    m["d1"]->print();
    m["d2"]->print();

    return 0;
}

答案 1 :(得分:2)

首先要做的事情:

template<class myClas>
map<string, myClass> m;

这不是有效的C ++,只能表示template alias,但我相信,这不是你想要的。

通过切片(从派生类型的值构造基类型的值),在C ++中存储多态对象很复杂。动态多态只能通过引用或指针来处理。您可以使用std::refboost::ref来处理地图只会在callstack中传递的情况,但这需要一些小心。通常,存储指向基础的指针是可行的方法:std::map<std::string, base*>。自己管理释放是相当繁琐的,并且首选std::map<std::string, std::unique_ptr>std::map<std::string, std::shared_ptr>,这取决于您是否需要共享语义。

基本示例。有人应该用更有意义的东西取而代之。

#include <memory>
#include <string>
#include <map>
#include <iostream>

class animal
{
public:
  virtual ~animal() {};
  virtual void make_sound() const = 0;
};

class dog : public animal
{
public:
  void make_sound() const { std::cout << "bark" << std::endl; }
};
class bird : public animal
{
public:
  void make_sound() const { std::cout << "chirp" << std::endl; }
};

int main()
{
  std::map<std::string, std::unique_ptr<animal>> m;
  m.insert(std::make_pair("stupid_dog_name", new dog));
  m.insert(std::make_pair("stupid_bird_name", new bird));
  m["stupid_dog_name"]->make_sound();
  return 0;
}

答案 2 :(得分:1)

您可能在类和函数上有模板,但实例上的不是

你应该坚持到地图BaseClass*'es。

答案 3 :(得分:1)

以下是anton建议的解决方案的扩展。

#include <iostream>
#include <string>
#include <map>
#include <utility>

using namespace std;

class BaseClass
{
    string s;

public: 
    BaseClass() { s = "BaseClass";} 
virtual ~ BaseClass(){}
virtual void print()=0;
};


class Derived1 : public BaseClass
{
    int i;
public:
    Derived1() { i = 10; }
    void print() 
    {
        cout << i << std::endl;
    }

};

class Derived2 : public Derived1
{
    float f;
public:
    Derived2() { f = 4.3;}
    void print() 
    {
        cout << f << std::endl;
    }
};

class factory
{
map<string, BaseClass*>m;
BaseClass* obj;
public:
factory()
{
obj=NULL;
}
BaseClass* FindType(string s);
void AddType(string s,BaseClass *obj);
void deleter();
~factory(){cout<<"deleting objects from map"<<endl;
deleter();
}
};
void factory :: AddType(string s,BaseClass* obj)
{ 
 m.insert(make_pair(s,obj ));
}
void factory ::deleter ()
 {

   for (auto  pObj = m.begin( );
        pObj != m.end( ); ++pObj) {

      delete pObj->second;
   }

   m.clear( );  

 }
BaseClass* factory::FindType(string s)
{
if(m.find(s)!=m.end())
{

return  m[s];
}

return NULL;
}

int main()
{   
   BaseClass* obj;
   factory fact_obj; 
   fact_obj.AddType("d1",new Derived1());
   fact_obj.AddType("d2",new Derived2());
   obj=fact_obj.FindType("d1");
   if(obj!=NULL)
      {
    obj->print();
      }
    obj=fact_obj.FindType("d2");
    if(obj!=NULL)
     {
     obj->print(); 
     }

    return 0;
}
相关问题