我已经定义了如下的接口类。
class IRecyclableObject
{
public:
virtual ~IRecyclableObject() {}
virtual void recycle() = 0;
virtual void dump() = 0;
virtual int getRecycleTypeID() = 0;
};
以下是我的 CharacterAI 类,它继承了另一个类并实现了上面的接口类。它的定义如下。
class CharacterAI : public harp::Character, public harp::IRecyclableObject
{
public:
CharacterAI();
virtual ~CharacterAI();
...
// -- note these 3 virtual functions -- //
virtual void recycle();
virtual void dump();
virtual int getRecycleTypeID();
...
};
接口中定义的那三个虚函数,我已经在 CharacterAI 类中实现了它。没什么好看的。
是时候将它们与 ObjectPool (一个自制的)类一起使用,其中可用对象的数据存储在
中m_freeList
使用 CCArray 类。
以下代码中出现此问题。
IRecyclableObject* ObjectPool::popFreeObjectAndAddToActiveListForType(int recycleTypeID)
{
// search from free-list
for(unsigned int i=0; i<m_freeList->count(); i++)
{
IRecyclableObject* obj = (IRecyclableObject*)m_freeList->objectAtIndex(i);
CharacterAI *obj1 = (CharacterAI*)m_freeList->objectAtIndex(i);
CCLog("recycleTypeID : %d %d %d", obj->getRecycleTypeID(), recycleTypeID, obj1->getRecycleTypeID());
...
}
return NULL;
}
预期结果显示
recycleTypeID : 4 4 4
但我得到了
recycleTypeID : 524241408 4 4
第一个显然是垃圾,并且每个循环随机不同。 我尝试在返回之前在 CharacterAI 类中的已实现函数 getRecycleTypeID() 中放置一个断点。我发现只有
obj1->getRecycleTypeID()
被召唤但不另一个。
通过关注 obj 变量,可以清楚地看到它看起来似乎是不同的对象调用,并且原因可能来自于将对象转换为接口类并使用if来自哪里它是错误的或者某种。
那里发生了什么? 我可以将对象类型类转换为接口类指针(它实现)并正确调用接口类中定义的函数吗?
答案 0 :(得分:9)
我可以将对象类转换为它实现的接口指针吗?
是。但那不是你的情况。函数objectAtIndex()
返回指向CCObject
的指针,该类肯定不实现IRecyclableObject
接口。
因此,CCObject*
到IRecyclableObject*
的残酷C风格转换将导致重新解释前一类型的对象的布局,就好像它是后一种类型的对象一样。这很糟糕,导致未定义的行为。
您应该使用dynamic_cast<>
将CCobject*
投射到IRecyclableObject*
:
IRecyclableObject* obj = dynamic_cast<IRecyclableObject*>(
m_freeList->objectAtIndex(i)
);
但是,请注意,如果您只希望指针最终转换为CharacterAI
类型的对象,则甚至不需要这样做。只需将其直接转换为该类型:
CharacterAI* obj = dynamic_cast<CharacterAI*>(m_freeList->objectAtIndex(i));
如果您尝试投射的指针指向的对象的运行时类型不是(等于或派生自)目标类型的向下转换,则 dynamic_cast<>
返回空指针。因此,在您不确定指向对象的具体类型的情况下,请不要忘记在解除引用之前检查返回的指针是否为非空。