【问题标题】:C++ Reducing the use of pointers, raw or otherwise and/or returning nullable non-pointersC++ 减少使用原始或其他指针和/或返回可为空的非指针
【发布时间】:2016-02-21 01:17:35
【问题描述】:

我正在使用 OpenGL 用 C++ 编写游戏,并决定编写一个基于组件的系统,这与 Unity 或 Unreal Engine 非常相似——为了好玩并了解这些系统是如何制作/工作的。我已经到了需要实现组件和游戏对象的地步,我已经非常成功地完成了。

我的实现是有效的……它只是不完全是我想要的。 目前,我将组件存储为组件指针的私有向量,并在请求时返回一个组件。

例子:

GetComponent<MeshRenderer>(); //Returns "MeshRenderer" Component as MeshRenderer*
AddComponent(new MeshRenderer(mesh)); //Adds component to vector + returns MeshRenderer*

组件是抽象类,由 MeshRenderer 等组件扩展。

T *AddComponent(T *component)
{
    component->parent = this;
    m_components[typeid(T).name()] = component;

    bool pushLocation = true;
    for (unsigned int i = 0; i < m_component_locations.size(); i++)
        if (m_component_locations.at(i) == typeid(T).name())
            pushLocation = false;
    if(pushLocation)
        m_component_locations.push_back(typeid(T).name());
    return GetComponent<T>();
}

上图:我的 AddComponent();代码,用于添加组件 - 需要一个指向组件的指针...

std::unordered_map<std::string, Component*> m_components; //Holds the components
std::vector<std::string> m_component_locations; //Holds data on components, allows them to be indexed

上图:我如何将我的组件存储在 GameObject 类中,让我可以按索引遍历它们

我对这种方法的问题是由于我如何实现我的 GetComponent() 函数。它返回一个指向组件的指针,如果不存在这样的组件,则可能返回一个 nullptr。

T *GetComponent()
{
    if (m_components.count(typeid(T).name()) != 0)
    {
        return static_cast<T*>(m_components[typeid(T).name()]);
    }
    else
    {
        return nullptr;
    }
}

我的问题是,由于返回一个指针,我可以调用 delete 并删除指针。这些是原始指针,但我确保它们在 GameObject 被销毁时由程序处理,所以 - 希望(除非我无能)不要担心内存泄漏 - 但我更愿意返回一个引用,因为您不能对它们调用“删除”这一事实 - 以避免我可能犯的任何愚蠢错误。

我已将变量设为私有,并且 GameObject 处理组件的删除,我不希望自己因无能等原因而删除某些内容。

我曾考虑返回一个 unique_ptr,但我不确定该实现是否更可取。

(作为额外说明,我确实需要 GetComponent() 函数来返回某种 null 或指示不存在此类组件)

【问题讨论】:

  • typeid(T).name() 你不应该以任何方式依赖它,仅将其用于调试目的,因为不能保证它到底是做什么的
  • 好的,你有什么建议我可以在不依赖typeid(t).name()的情况下改变它以实现同样的用途吗?
  • 你可以使用哈希码或std::type_index,见注释:en.cppreference.com/w/cpp/language/typeid
  • 既然你提到了unique_ptr,我会提到还有shared_ptr(在C++11中);可能感兴趣也可能不感兴趣
  • 这样会更好吗? std::type_index(typeid(T)) 已经很晚了,所以我只是略读了一下 type_index 文章,但我明天会好好检查一下。

标签: c++ pointers reference raw-pointer


【解决方案1】:

您减少使用原始指针的想法是正确的。我认为您必须查看EntityX library 并注意事情是如何实现的。那里根本没有指针。

对于您的情况,您必须执行与 EntityX 相同的操作 - 创建类 ComponentHandle 并引用(而非指针)您的组件。此类不管理组件的生命周期。它只是您的组件的一个接口。您还可以重载 -&gt; 运算符以访问组件中的成员。

祝你在 C++ 和组件实体系统中好运。

【讨论】:

  • EntityX 的解决方案正是我所需要的,谢谢。
  • @Freak_ey 这听起来有点像std::reference_wrapper,也许你也应该喜欢它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-25
  • 2016-06-10
  • 2017-05-13
  • 2019-08-25
  • 2013-04-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多