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

hax*_*por 5 c++ casting interface cocos2d-x

我已经定义了如下所示的接口类.

class IRecyclableObject
{
public:
    virtual ~IRecyclableObject() {}

    virtual void recycle() = 0;
    virtual void dump() = 0;
    virtual int getRecycleTypeID() = 0;
};
Run Code Online (Sandbox Code Playgroud)

以下是我的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();

    ...
};
Run Code Online (Sandbox Code Playgroud)

接口中定义的那三个虚函数,我已经在CharacterAI类中实现了它.没有什么花哨的.

是时候将它们与ObjectPool(一个自制的)类一起使用,其中可用对象的数据存储在

m_freeList
Run Code Online (Sandbox Code Playgroud)

使用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;
}
Run Code Online (Sandbox Code Playgroud)

预期的结果是显示

recycleTypeID : 4 4 4
Run Code Online (Sandbox Code Playgroud)

但是我得到了

recycleTypeID : 524241408 4 4
Run Code Online (Sandbox Code Playgroud)

第一个显然是垃圾,并且每个循环随机不同.我试图在返回之前在CharacterAI类中的实现函数getRecycleTypeID()中放置一个断点.我发现只有

obj1->getRecycleTypeID()
Run Code Online (Sandbox Code Playgroud)

被召唤但不是另一个.

通过关注obj变量,可以清楚地看到它看起来似乎是不同的对象调用,并且原因可能来自于将对象转换为接口类,并且如果从那里使用它是错误的或某种类型的话.

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

And*_*owl 9

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

是.但那不是你的情况.函数objectAtIndex()返回一个指向CCObject,那类绝对不会实现IRecyclableObject接口.

因此,残酷的C样式CCObject*转换IRecyclableObject*将导致重新解释前一类型的对象的布局,就好像它是后一种类型的对象一样.这很糟糕,并导致未定义的行为.

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

IRecyclableObject* obj = dynamic_cast<IRecyclableObject*>(
    m_freeList->objectAtIndex(i)
    );
Run Code Online (Sandbox Code Playgroud)

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

CharacterAI* obj = dynamic_cast<CharacterAI*>(m_freeList->objectAtIndex(i));
Run Code Online (Sandbox Code Playgroud)

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