【问题标题】:Get derived class of base-class pointer获取基类指针的派生类
【发布时间】:2016-02-15 10:03:19
【问题描述】:

我正在寻找一种将我的基类指针转换为派生类指针以访问其成员函数的方法。我尝试过动态转换,但是当尝试将派生类函数打印到 cout 时,我的程序停止工作。

这是我的代码:

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

我需要知道如何正确地将我的基类指针转换为派生指针。我的基类 Entity 只拥有一个唯一的 id 来识别我的游戏中的对象(在我的第一个游戏引擎上工作;我对 C++ 很陌生),派生类将是玩家、瓷砖等比基类更多的功能。使用我的地图,我的目标是有一个识别选项,将所有指向我的游戏对象的指针放在一个地方。因此,如果我有一个类实例的 id,我就可以通过指针完全访问它的功能。

插入:

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

获取实体:

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

【问题讨论】:

  • 向我们展示您是如何在std::map中插入的
  • 如果你想使用BoxObject,你需要创建BoxObject,而不是Entitydynamic_cast 不会神奇地将一个对象变成另一种对象。
  • 我有点惊讶dynamic_cast 带有运行时类型检查并没有抛出任何错误(因为他正在向下转换)。也许我错了。我是吗?
  • @ubuntugod dynamic_cast 如果无法执行转换,将返回 nullptr
  • @JonathanPotter 谢谢。我对 C++ 相当陌生。我相信dynamic_cast 会抛出异常(bad_cast),如果它是引用而不是指针。

标签: c++ pointers


【解决方案1】:

在创建box2时,实际上是在创建Entity的对象,如下:

g_pEntityManager-&gt;addEntity(std::make_unique&lt;Entity&gt;(box2));

相反,如果你想要一个派生类的对象(BoxObject),你需要创建这样一个对象:

g_pEntityManager-&gt;addEntity(std::make_unique&lt;BoxObject&gt;(box2));

然后可以按如下方式使用:

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

【讨论】:

  • 是否可以创建不同 std::make_unique 的地图?就像将 std::make_unique 和 std::make_unique 放到同一张地图中一样?
  • 不。 std::map 中的所有键必须属于同一类型。但是由于BoxObject 是从Entity 派生的,所以上面的方法可以工作,因为m_EntityManager 的键是std::unique_ptr&lt;Entity&gt; 类型的。
  • 啊,好的,谢谢。有时就是这么简单 =) 现在可以正常工作了
猜你喜欢
  • 2012-01-07
  • 2011-07-20
  • 1970-01-01
  • 1970-01-01
  • 2016-05-25
  • 1970-01-01
  • 1970-01-01
  • 2016-12-02
  • 1970-01-01
相关资源
最近更新 更多