5

我已经定义了一个如下的接口类。

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 从那里它是错误的或某种类型。

那里发生了什么事?我可以将对象类型类转换为接口类指针(它实现)并正确调用接口类中定义的函数吗?

4

1 回答 1

9

我可以将对象类转换为它实现的接口指针吗?

是的。但这不是你的情况。函数objectAtIndex()返回一个指向 a 的指针CCObject,并且该类肯定没有实现该IRecyclableObject接口。

因此,粗暴的 C 风格CCObject*转换 toIRecyclableObject*将导致重新解释前一种对象的布局,就好像它是后一种类型的对象一样。这很糟糕,并导致Undefined Behavior

您应该使用dynamic_cast<>将您的CCobject*转换为IRecyclableObject*

IRecyclableObject* obj = dynamic_cast<IRecyclableObject*>(
    m_freeList->objectAtIndex(i)
    );

但是请注意,如果您只想将指针最终转换为 type 的对象,则甚至不需要这样做CharacterAI。只需直接将其转换为该类型:

CharacterAI* obj = dynamic_cast<CharacterAI*>(m_freeList->objectAtIndex(i));

dynamic_cast<>如果您尝试转换的指针指向的对象的运行时类型不是(等于或派生自)向下转换的目标类型,则返回空指针。因此,在不确定指向对象的具体类型的情况下,不要忘记在取消引用之前检查返回的指针是否为非空。

于 2013-02-17T17:11:09.743 回答