0
votes

I'm looking for a way to cast my base-class-pointer to a derived-class-pointer to get access to its member-functions. I've tried dynamic casting, but when trying to print the derived class-functions to cout, my program stops working.

Here is my code:

int main()
{
    Entity box;
    BoxObject box2(10, 10, 33, 2,BODYTYPE::dynamicBody);

    // adding my entities to my std::map
    g_pEntityManager->addEntity(std::make_unique<Entity>(box));
    g_pEntityManager->addEntity(std::make_unique<Entity>(box2));

    // get Entity with Entity* as return value
    // (1) is the unique id as key of my map
    Entity* ent = g_pEntityManager->getEntity(1);

    // casting Entity* to BoxObject* to be able to have access to derived- 
    // class member-functions
    BoxObject* boxi = dynamic_cast<BoxObject*>(ent);

    // when trying to cout public member function program crashes
    std::cout << boxi->getDimension().x << std::endl;
    return 0;
}

I need to know how I can properly transform my base-class-pointer to a derived-one. My base-class Entity only holds a unique id to identify the object in my game (working on my first game engine; I'm pretty new to C++), the derived classes are going to be players, tiles, etc. with more functions than the base-class has. With my map, my goal is to have a identification-option to have all the pointers to my game-objects in one place. So if I have the id of an class-instance, I'd be able to have full access to its functions via the pointer.

Inserting:

int EntityManager::addEntity(std::unique_ptr<Entity> gameObject)
{
    int size = m_EntityManager.size();
    gameObject->setID(size);
    // add entity-object to EntityManager and increment entity_id;
    m_EntityManager.insert(std::make_pair(size, std::move(gameObject)));
    std::cout << "Entity added! " << m_EntityManager.size() << std::endl;
    m_nEntityCounter ++;
    return size;
}

Get Entity:

Entity* EntityManager::getEntity(int entityId)
{
    std::map<int, std::unique_ptr<Entity>>::iterator it = m_EntityManager.find(entityId);
    if (it != m_EntityManager.end())
    {
        if (it->second != nullptr)
        {
            std::cout << "GEt: " << it->second.get() << std::endl;
            return it->second.get();
        }
        else
        {
            std::cout << "Pointer to object is invalid!" << std::endl;
            return nullptr;
        }
    }
    else 
    {
        std::cout << "Couldn`t find Entity with id: " << entityId << " in EntityManager" << std::endl;
        return nullptr;
    }
}
1
Show us how you are inserting in your std::mapCinCout
If you want to use a BoxObject you need to create a BoxObject, not an Entity. dynamic_cast does not magically transform one object into a different kind of obejct.molbdnilo
I am bit surprised that dynamic_cast with an run-time type checking didn't throw any error (as he was downcasting). Maybe I am wrong. Am I?ubuntugod
@ubuntugod dynamic_cast will return nullptr if the cast can not be performed.Jonathan Potter
@JonathanPotter Thanks. I'm fairly new to C++. I believe dynamic_cast would throw an exception (bad_cast) if it was reference instead of the pointer.ubuntugod

1 Answers

2
votes

While creating box2, you are actually creating an object of Entity, as follows:

g_pEntityManager->addEntity(std::make_unique<Entity>(box2));

Instead, if you want an object of derived class (BoxObject), you need to create such an object:

g_pEntityManager->addEntity(std::make_unique<BoxObject>(box2));

This can then be used as follows:

Entity* ent = g_pEntityManager->getEntity(1);
BoxObject* boxi = dynamic_cast<BoxObject*>(ent);