我想知道是否可以创建一个继承类指针的映射。以下是我正在尝试做的一个例子:
#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
我明白为什么我会收到此错误,但我想知道是否可以创建一个可以容纳不同级别的继承类的地图?如果没有,是否有可能创建一种可以容纳各种类型的管理系统?或者我是否必须制作不同的地图/矢量/数组/等。对于每种类型的课程?
答案 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::ref
或boost::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;
}