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

时间:2013-02-17 16:55:31

标签: c++ interface casting cocos2d-x

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

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来自哪里它是错误的或者某种。

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

1 个答案:

答案 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<>返回空指针。因此,在您不确定指向对象的具体类型的情况下,请不要忘记在解除引用之前检查返回的指针是否为非空。