获取基类的指针以使用派生类的函数

时间:2016-02-14 22:23:57

标签: c++ pointers c++11 dictionary unique-ptr

我正在尝试创建基类(实体)的unique_ptr映射,其中只存储唯一的ID来标识我的对象。现在我想创建不同的派生类(如播放器,磁贴等),它们应该从基类派生出来,以获得唯一的标识。

如何将unique_ptr的内存位置作为返回值传递而不将其移出我的地图?我的想法是在将派生类传递到我的地图时使用基类的内存位置来访问派生函数。

P.S。我目前正在开发自己的游戏引擎(仍然是cpp的新手)

这是我目前的EntityManager WIP:

EntityManager.hpp

#pragma once
#include "TSingleton.hpp"
#include "Entity.hpp"
#include <map>
#include <iostream>
#include <memory>

#define g_pEntityManager EntityManager::Get()

class EntityManager : public TSingleton<EntityManager>
{
public:
    EntityManager();
    ~EntityManager();
    // add entity to entity-manager and returns id in entityManager
    int addEntity(std::unique_ptr<Entity> gameObject);

    // get pointer to entityManager
    std::map<int, std::unique_ptr<Entity>> getEntityManager() { return m_EntityManager; };

    // destroy entity
    void killEntity(int entityId);

    // get entity
    std::unique_ptr<Entity> getEntity(int entityId);
private:
    int m_nEntityCounter = 0;

    std::map<int, std::unique_ptr<Entity>> m_EntityManager;
};

EntityManager.cpp

EntityManager::EntityManager()
{
}


EntityManager::~EntityManager()
{
}

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

void EntityManager::killEntity(int entityId)
{
    std::map<int, std::unique_ptr<Entity>>::iterator it = m_EntityManager.find(entityId);

    if (it != m_EntityManager.end())
    {
        m_EntityManager.erase(it);
    }
    else
        std::cout << "Couldn`t kill Entity with id: " << entityId << " , because there is no Entity with this id in EntityManager" << std::endl;
}

std::unique_ptr<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::unique_ptr<Entity>& found = it->second;
            return std::move(found);
        }
        else
            std::cout << "Pointer to object is NULL!" << std::endl;
    }
    else
        std::cout << "Couldn`t find Entity with id: " << entityId << " in EntityManager" << std::endl;
}

1 个答案:

答案 0 :(得分:1)

根本不可能在不移动的情况下按值返回unique_ptr。

你可以做的是这些事情之一:

返回原始指针:

Entity* EntityManager::getEntity(int entityId)
{
   return it->second.get();
}

返回对unique_ptr的引用:

std::unique_ptr<Entity>& EntityManager::getEntity(int entityId)
{
   return it->second;
}

&#34;问题&#34;通过引用返回是您始终需要返回对对象的有效引用。在过去,我使用了创建例如static std::unique_ptr<Entity> EmptyEntity对象的策略,如果getEntity无法在地图中找到它,则会返回它。

例如:

static std::unique_ptr<Entity> EmptyEntity;

std::unique_ptr<Entity>& EntityManager::getEntity(int entityId)
{
    if (it == container.end())
        return EmptyEntity;

    return it->second;
}

另一个解决方案是通过指针返回unique_ptr,如果找不到任何实体,则返回nullptr。如果你这样做,那么更容易使用Entity* EntityManager::getEntity()