您可以创建继承类的 std::map 吗?

发布于 2024-12-23 04:13:36 字数 757 浏览 2 评论 0原文

我想知道是否可以创建继承类的指针映射。这是我想要做的一个示例:

#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

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

I'm wondering if it's possible to create a map of pointers of inherited classes. Here's an example of what I'm trying to do:

#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;
}

The errors I get are:

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

I get why I'm getting this error, but I'm wondering if it's possible to create a map that can hold different levels of inherited classes? If not, is it possible to create some sort of management system that can hold various class types? Or would I have to make different maps/vectors/arrays/etc. for each type of class?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

后eg是否自 2024-12-30 04:13:36

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

#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;
}

Yes you can store inherited classes in map, but pointers to them, not objects themselves. Here's a short example (it lacks memory management on pointers)

#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;
}
故人爱我别走 2024-12-30 04:13:36

首先要做的事情是:

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

这不是有效的 C++,只能意味着类似模板别名的东西,但我相信,这不是您正在寻找的东西。

在 C++ 中存储多态对象由于切片(从派生类型的值构造基类型的值)而变得复杂。动态多态只能通过引用或指针来处理。对于映射仅在调用堆栈中传递的情况,您可以使用 std::refboost::ref,但这需要小心。通常,存储指向基址的指针是可行的方法:std::map。自己管理释放是相当乏味的,或者 std::mapstd::map< /code> 是首选,具体取决于您是否需要共享语义。

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

#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;
}

First things first:

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

This is not valid C++ and could only mean something like a template alias, but I believe, that is not what you are looking for.

Storing polymorphic objects in C++ is complicated by slicing (constructing a value of the base type from a value of a derived type). Dynamic polymorphism can only be handled through references or pointers. You could potentially use std::ref or boost::ref for situations in which the map will only be passed down the callstack, but this requires some care. Often, storing pointers to the base is the way to go: std::map<std::string, base*>. Managing deallocation yourself is rather tedious and either std::map<std::string, std::unique_ptr> or std::map<std::string, std::shared_ptr> are preferred, depending if you need shared semantics or not.

Basic example. Someone should replace this with something more meaningful.

#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;
}
时光倒影 2024-12-30 04:13:36

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

您应该坚持使用 BaseClass* 的映射。

You may have template on classes and functions, but not on instances.

You should stick to the map to BaseClass*'es.

聽兲甴掵 2024-12-30 04:13:36

下面是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;
}

Below is the expansion of solution suggested by 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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文