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

12,473

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

Yes. But that's not your case. Function objectAtIndex() returns a pointer to a CCObject, and that class definitely does not implement the IRecyclableObject interface.

Thus, a brutal C-style cast of CCObject* to IRecyclableObject* will result in reinterpreting the layout of an object of the former type as if it was an object of the latter type. That's bad, and leads to Undefined Behavior.

You should use dynamic_cast<> to cast your CCobject* to a IRecyclableObject*:

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

Notice, however, that this is not even needed if you just want your pointer to be eventually cast to an object of type CharacterAI. Just directly cast it to that type:

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

dynamic_cast<> returns a null pointer if the run-time type of the object pointed to by the pointer you are trying to cast is not (equal to or derived from) the target type of the downcast. Therefore, in those cases where you are not sure about the concrete type of the pointed object, don't forget to check whether the returned pointer is non-null before dereferencing it.

Share:
12,473
haxpor
Author by

haxpor

Maker Gamedev • Linux • Open source Twitter: @haxpor Website: https://wasin.io

Updated on June 14, 2022

Comments

  • haxpor
    haxpor almost 2 years

    I have defined an interface class like the following.

    class IRecyclableObject
    {
    public:
        virtual ~IRecyclableObject() {}
    
        virtual void recycle() = 0;
        virtual void dump() = 0;
        virtual int getRecycleTypeID() = 0;
    };
    

    The following is my CharacterAI class which inherits another class and implements above interface class. It's defined as follows.

    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();
    
        ...
    };
    

    Those three virtual functions as defined in interface, I have implemented it normally in CharacterAI class. Nothing fancy goes there.

    It's time when I put them into use with ObjectPool (a self-made) class in which the data storage of available objects in

    m_freeList
    

    uses CCArray class.

    The problem occurs in the following code.

    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;
    }
    

    The expected result is to show

    recycleTypeID : 4 4 4
    

    But I got

    recycleTypeID : 524241408 4 4
    

    The first one is clearly garbage there and randomly different from each loop. I tried to put a breakpoint in the implemented function getRecycleTypeID() inside CharacterAI class before it returns. I found out that only

    obj1->getRecycleTypeID()
    

    was called but not another.

    By focusing on obj variable, It's clearly seen that it seems different object calls that function, and the cause may come from casting an object to interface class and use if from there in which it's wrong or some kind.

    What's going on there? Can I cast an object type class to interface class pointer (which it implements) and correctly call functions as defined in interface class?

  • haxpor
    haxpor about 11 years
    That solved my problem, and thanks to make me pay more attention to dynamic_cast, and other casting type not just c-style cast. It's about RTTI and runtime I'm dealing with it in this problem. Now I figure my own part of problem in other codes. Thanks!
  • Andy Prowl
    Andy Prowl about 11 years
    @haxpor: Glad it helped :-)