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

Can I cast an object class to the interface pointer in which it implements?

本文关键字:实现 接口 指针 转换 对象 我可以      更新时间:2023-10-16

我定义了一个接口类,如下所示。

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

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

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

是的。但事实并非如此。函数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<>返回一个空指针。因此,在那些不确定所指向对象的具体类型的情况下,在取消引用之前,不要忘记检查返回的指针是否为非null。