我在头文件中定义了以下模板函数。
template <class T> T* spawnEnemy(SpawnDirection dir);
我的目的是创建一个通用的产卵函数,接受敌人的类型作为模板参数,并从函数中返回衍生的对象。
以下是不正确的实施,但我用它来表达我想要实现的目标。
template <class T> T* ObjectSpawner::spawnEnemy(SpawnDirection dir)
{
if(_enemiesPool->isAnyFreeObjects())
{
T* enemy = NULL;
if(typeof(T*) == Zombie01) // This line is INCORRECT
enemy = dynamic_cast<T*>(_enemiesPool->popFreeObjectAndAddToActiveListForType(ZOMBIE));
else if ...
return enemy;
}
else
return NULL;
}
那就是我需要能够从 T 进行类型检查,所以我可以适当地调用函数
popFreeObjectAndAddToActiveListForType(int type)
以正确的值作为输入。
那么如何在模板函数中进行类似情况的类型检查呢?
编辑: 在得到stephen lin和nvoigt的建议之后,我发现这个设计有一个缺陷,但这是因为我已经从我已经充实了。更容易让函数有另一个类型参数,不涉及模板但需要稍后转换为特定类型。无论如何,知道这种情况的解决方案是很好的。
答案 0 :(得分:1)
一种可能是使用dynamic_cast
,如果T
是Zombie01
的基类:
T *enemy = dynamic_cast<Zombie01*>(x);
if (!enemy)
{
// x can not cast to Zombie01
// do something else
}
但是,建议尽量减少dynamic_cast
另一个想法是使用std::is_same
:
如果T和U使用相同的const-volatile命名相同的类型 资格,提供成员常数值等于true。 否则值为false。
但是,我正在尝试使用Scott Meyers的Effective C ++提示:
“任何时候你发现自己编写表单的代码”如果对象是 T1类型,然后做一些事情,但如果它是T2类型,那么做 别的什么,“打自己。”
答案 1 :(得分:1)
我认为你想要这样的事情(使用类型特征):
以下代码部分必须放在课程部分之外。
template <typename T>
struct EnemyTraits { };
template <>
struct EnemyTraits<Zombie01> { static const int pop_type = ZOMBIE; };
template <>
struct EnemyTraits<Vampire01> { static const int pop_type = VAMPIRE; };
应在this中建议的头文件中定义以下函数。
template <typename T> T* ObjectSpawner::spawnEnemy(SpawnDirection dir)
{
if(_enemiesPool->isAnyFreeObjects())
{
const int pop_type = EnemyTraits<T>::pop_type;
return dynamic_cast<T*>(_enemiesPool->popFreeObjectAndAddToActiveListForType(pop_type));
}
else
return NULL;
}