我正在为我的一个项目构建一个简单的游戏设计。我有以下课程:
class Character
{
public:
virtual void Display();
virtual void SetParameters( char* param, ... );
};
class NonPlayableCharacter : public Character
{
public:
virtual void Display();
virtual void SetParameters( char* paaram, ... );
int GetNPCState();
}
然后我有一堆派生于Character或NonPlayableCharacter的类。我这样定义:
std::vector<Character*> _allChar;
我的问题是,在任何给定的时间,我都想对矢量的一个元素执行一些操作。因此,从向量中获取元素我无法直接调用方法GetNPCState()
,因为向量中的元素是Character *类型。所以这样做:
_allChar[0]->GetNPCState();
不起作用。所以我尝试使用着名的dynamic_cast:
NonPlayableCharacter* test = dynamic_cast<NonPlayableCharacter*>(_allChar[0]);
test->GetNPCState();
最后一次尝试的问题是GetNPCState()
崩溃,因为对象为空,我知道(通过调试)_allChar [0]不为空。
答案 0 :(得分:6)
C ++(4)中有几种类型的强制类型,其中2种是有兴趣的:
static_cast
假设您知道自己在做什么dynamic_cast
在运行时检查您是否已经猜到&#34;右 注意:简化,因为dynamic_cast
也允许包含虚拟基础的交叉投射和强制转换。
dynamic_cast
有3个版本,实际上,取决于目标的性质:
dynamic_cast<T&>(u)
),那么如果检查失败dynamic_cast
则会引发std::bad_cast
异常dynamic_cast<T*>(p)
),那么如果检查失败dynamic_cast
则返回空指针void*
,则dynamic_cast
会返回完整对象的地址在这种情况下,您可以:
dynamic_cast<NonPlayableCharacter*>(_allChar[0])->getNPCState()
切换到
dynamic_cast<NonPlayableCharacter&>(*_allChar[0]).getNPCState()
,让异常传播NonPlayableCharacter* test
此处)的非无效性答案 1 :(得分:5)
在
NonPlayableCharacter* test = dynamic_cast<NonPlayableCharacter*>(_allChar[0]);
您应该检查test
是否为NULL
。即使_allChar[0]
不是NULL,dynamic_cast
如果指向的对象不是NULL
,也可以返回NonPlayableCharacter
。
所以正确的版本是:
NonPlayableCharacter* test = dynamic_cast<NonPlayableCharacter*>(_allChar[0]);
if (test)
{
test->GetNPCState();
}
答案 2 :(得分:3)
dynamic_cast
会返回NULL
。检查_allChar[0]
内的内容。您可以使getType()
之类的函数返回对象预定义的类型ID,然后使用static_cast
:
if (_allChar[0]->getType() == TYPE_NO_PLAYER) {
static_cast<NonPlayableCharacter*>(_allChar[0])->getNpcState();
}
答案 3 :(得分:2)
您必须测试dynamic_cast
是否成功。它在失败时返回空指针:
NonPlayableCharacter* test = dynamic_cast<NonPlayableCharacter*>(_allChar[0]);
if (test) test->GetNCPState();
问题可能是你的第一个元素没有指向NonPlayableCharacter
对象。
答案 4 :(得分:2)
dynamic_cast
在其参数未指向NULL
时返回NonPlayableCharacter
(因此数组中的第一个元素可能指向Character
的其他子类) - 所以你需要在演员表之后检查NULL
。但是,使用dynamic_cast
可能表示存在设计问题。也许您应该在Character
上使用虚拟方法,例如PerformMainActionInGameLoop()
并在不同的子类中被适当地覆盖?
答案 5 :(得分:2)
要从基指针获取子指针,您必须使用dynamic_cast
。其行为如下:
Child*
的{{1}},则new Child
会返回dynamic_cast<Child*>
Child*
会返回dynamic_cast
。您的问题是,您未使用NULL
分配,或者您的对象属于不同类型。
答案 6 :(得分:2)
使用dynamic_cast可能有更好的OO解决方案,但使用此强制转换的全部意义在于,如果转换失败,它将返回NULL指针。
因此在调用GetNPCState();
之前检查NULLNonPlayableCharacter* test = dynamic_cast<NonPlayableCharacter*>(_allChar[0]);
if( test != NULL )
{
test->GetNPCState();
}