您将创建的类型是否具有公共基础?
正如在C++中不能有无关类型的集合(vector/map)一样,类型应该有一个公共基类,以便下面的代码工作。(否则,可以使用void*,但转换将不安全):
#include <iostream>
#include <map>
class Entity {
public:
virtual ~Entity(){}
};
class C1: public Entity
{
public:
void doSomething(){std::cout << "C1" << std::endl;}
};
class C2: public Entity
{
public:
void doSomething(){std::cout << "C2" << std::endl;}
};
class C3
{
public:
void doSomething(){std::cout << "C3" << std::endl;}
};
class CreatorBase {
public:
virtual ~CreatorBase () {};
virtual Entity* create () = 0;
};
template<typename T>
class Creator: public CreatorBase {
public:
Entity* create ()
{
return new T;
}
};
std::map<int, CreatorBase*> cmap;
这里,我们有一个基本Entity类,C1和C2继承自它。
接下来是模板类Creator,它创建一个请求类型的对象。
它们都继承自Creator Base,因此可以存储在地图中。
创建者返回Entity*,为了类型安全,我们可以在调用create()时使用动态强制转换,以确保创建的类型正确。
如果只需要Entity指针,则可以在任何地方使用Entity*,而不需要动态转换。
int main(int argc, char *argv[])
{
cmap[1]=new Creator<C1>;
cmap[2]=new Creator<C2>;
//cmap[3]=new Creator<C3>; //will not compile - C3 does not derive from Entity
C1 *i1 = dynamic_cast<C1*> (cmap[1]->create());
C2 *i2 = dynamic_cast<C2*> (cmap[2]->create());
C1 *i3 = dynamic_cast<C1*> (cmap[2]->create()); //bad dynamic cast: cmap[2] does not create C1
if (!i1) {
std::cout << "i1: Bad dynamic cast" << std::endl;
} else {
i1->doSomething();
}
if (!i2) {
std::cout << "i2: Bad dynamic cast" << std::endl;
} else {
i2->doSomething();
}
if (!i3) {
std::cout << "i3: Bad dynamic cast" << std::endl;
} else {
i3->doSomething();
}
}
输出:
C1
C2
i3: Bad dynamic cast