std::vector 带有模板参数
std::vector with a template argument
我得到了这样的代码:
template<class T> void Engine::extend( std::string name ) {
T *instance = new T( this );
this->newExtensions[name] = instance;
}
这样称呼:
engine.extend<Menu>( "menu" );
它工作得很好,但我想稍后在我的代码中(在我的游戏的主循环中)创建一个 T
的新实例,而不是在 Engine::extend
方法中这样做.是否可以保留有关 class 的信息以向量或任何其他将在整个 Engine
class 中共享的数据结构进行实例化,以便我稍后可以在其他方法中调用它?我想要实现的伪代码:
template<class T> void Engine::extend( std::string name ) {
this->newExtensions[name] = T;
}
您要创建的类型是否有共同的基础?
与在 C++ 中一样,您不能拥有不相关类型的集合(向量/映射),类型应该有一个公共基础 class 才能使以下代码正常工作。 (否则,您可以使用 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;
在这里,我们有一个基础实体 class,C1 和 C2 继承自它。
接下来是模板classCreator,它创建一个请求类型的对象。
都是继承自CreatorBase,所以可以存储在一个map中。
创建者 returns 实体*,为了类型安全,我们可以在调用 create() 时使用动态转换,以确保我们正在创建正确的类型。
如果你只需要一个实体指针,你可以在任何地方使用实体*,不需要动态转换。
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
我得到了这样的代码:
template<class T> void Engine::extend( std::string name ) {
T *instance = new T( this );
this->newExtensions[name] = instance;
}
这样称呼:
engine.extend<Menu>( "menu" );
它工作得很好,但我想稍后在我的代码中(在我的游戏的主循环中)创建一个 T
的新实例,而不是在 Engine::extend
方法中这样做.是否可以保留有关 class 的信息以向量或任何其他将在整个 Engine
class 中共享的数据结构进行实例化,以便我稍后可以在其他方法中调用它?我想要实现的伪代码:
template<class T> void Engine::extend( std::string name ) {
this->newExtensions[name] = T;
}
您要创建的类型是否有共同的基础? 与在 C++ 中一样,您不能拥有不相关类型的集合(向量/映射),类型应该有一个公共基础 class 才能使以下代码正常工作。 (否则,您可以使用 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;
在这里,我们有一个基础实体 class,C1 和 C2 继承自它。 接下来是模板classCreator,它创建一个请求类型的对象。
都是继承自CreatorBase,所以可以存储在一个map中。
创建者 returns 实体*,为了类型安全,我们可以在调用 create() 时使用动态转换,以确保我们正在创建正确的类型。
如果你只需要一个实体指针,你可以在任何地方使用实体*,不需要动态转换。
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