C++ 减少指针、原始指针或其他指针的使用 and/or 返回可为空的非指针
C++ Reducing the use of pointers, raw or otherwise and/or returning nullable non-pointers
我正在使用 OpenGL 在 C++ 中编写一个游戏,并决定编写一个基于组件的系统,非常类似于 Unity 或 Unreal Engine - 为了好玩并了解这些系统是如何 made/work。我已经到了需要实现组件和游戏对象的地步,我已经做得相当成功了。
我的实现工作正常...只是不是我想要的那样。
目前,我将组件存储为指向组件的指针的私有向量,并在请求时 return 一个组件。
示例:
GetComponent<MeshRenderer>(); //Returns "MeshRenderer" Component as MeshRenderer*
AddComponent(new MeshRenderer(mesh)); //Adds component to vector + returns MeshRenderer*
组件是抽象的 classes 并且由 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 class 中,允许我通过索引循环遍历它们
我对这种方法的问题是由于我如何实现我的 GetComponent() 函数。它 return 是一个指向组件的指针,如果不存在这样的组件,则可能是一个 nullptr。
T *GetComponent()
{
if (m_components.count(typeid(T).name()) != 0)
{
return static_cast<T*>(m_components[typeid(T).name()]);
}
else
{
return nullptr;
}
}
我的问题是,由于 returning 指针,我可以调用 delete 并删除指针。这些是原始指针,但我已确保在销毁 GameObject 时由程序处理它们 - 希望(除非我无能)不用担心内存泄漏 - 但我更愿意 return一个参考,因为你不能对它们调用 "delete" - 以避免我可能犯的任何愚蠢的错误。
我已将变量设为私有,GameObject 处理组件的删除,我不想让自己因为无能等原因删除某些内容。
我考虑过 returning unique_ptr 但我不确定该实施是否更可取。
(作为额外说明,我确实需要 GetComponent() 函数来 return 某种 null 或给出不存在此类组件的指示)
您减少使用原始指针的想法是正确的。我认为您必须研究 EntityX library 并注意事情是如何实施的。那里根本没有指针。
对于您的情况,您必须做与 EntityX
相同的事情 - 创建 class ComponentHandle
并引用(而不是指针)到您的组件。 class 不管理组件的生命周期。它只是您的组件的一个接口。您还可以重载 ->
运算符以访问组件中的成员。
祝你在 C++ 和组件实体系统方面好运。
我正在使用 OpenGL 在 C++ 中编写一个游戏,并决定编写一个基于组件的系统,非常类似于 Unity 或 Unreal Engine - 为了好玩并了解这些系统是如何 made/work。我已经到了需要实现组件和游戏对象的地步,我已经做得相当成功了。
我的实现工作正常...只是不是我想要的那样。 目前,我将组件存储为指向组件的指针的私有向量,并在请求时 return 一个组件。
示例:
GetComponent<MeshRenderer>(); //Returns "MeshRenderer" Component as MeshRenderer*
AddComponent(new MeshRenderer(mesh)); //Adds component to vector + returns MeshRenderer*
组件是抽象的 classes 并且由 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 class 中,允许我通过索引循环遍历它们
我对这种方法的问题是由于我如何实现我的 GetComponent() 函数。它 return 是一个指向组件的指针,如果不存在这样的组件,则可能是一个 nullptr。
T *GetComponent()
{
if (m_components.count(typeid(T).name()) != 0)
{
return static_cast<T*>(m_components[typeid(T).name()]);
}
else
{
return nullptr;
}
}
我的问题是,由于 returning 指针,我可以调用 delete 并删除指针。这些是原始指针,但我已确保在销毁 GameObject 时由程序处理它们 - 希望(除非我无能)不用担心内存泄漏 - 但我更愿意 return一个参考,因为你不能对它们调用 "delete" - 以避免我可能犯的任何愚蠢的错误。
我已将变量设为私有,GameObject 处理组件的删除,我不想让自己因为无能等原因删除某些内容。
我考虑过 returning unique_ptr 但我不确定该实施是否更可取。
(作为额外说明,我确实需要 GetComponent() 函数来 return 某种 null 或给出不存在此类组件的指示)
您减少使用原始指针的想法是正确的。我认为您必须研究 EntityX library 并注意事情是如何实施的。那里根本没有指针。
对于您的情况,您必须做与 EntityX
相同的事情 - 创建 class ComponentHandle
并引用(而不是指针)到您的组件。 class 不管理组件的生命周期。它只是您的组件的一个接口。您还可以重载 ->
运算符以访问组件中的成员。
祝你在 C++ 和组件实体系统方面好运。