我正在尝试用 C++ 创建一个类似于 Unity3d 中的“组件管理器”类。我想要的是一个容器类,它可以容纳某些类的派生类型,比如 BaseComponent。在统一中,可以通过以下方式以类型安全的方式请求使用泛型的组件
manager.GetComponent() 返回类型为DerivedComponentType&
我想要 C++ 中的相同接口(interface)。这样,只要通过 AddComponent 函数添加组件,就可以保证整个过程从使用的角度来看是类型安全的。
我在这里试图避免使用字符串进行标识之类的事情。我意识到我也可以通过给每个派生类型一个同名的静态成员函数并将其地址用作类实例的映射索引来做到这一点。我宁愿不这样做,这样组件管理器的用户在选择派生自己的组件时就不必确保此函数存在。
谢谢。
最佳答案
一种方法是使用 dynamic_cast。
template <typename Derived>
Derived* GetComponent (void)
{
// componentlist is a std::vector<BaseClass*>
for (unsigned i = 0; i < componentlist.size(); ++i)
{
Derived* val = dynamic_cast<Derived*>(componentlist[i]);
if (val != 0)
return val;
}
return 0;
}
如果类型与模板给出的不匹配,dynamic_cast 将给出一个空指针。当然,这是必须在运行时完成的事情。在现代机器上,除非您经常这样做,否则这不会造成太大影响。还有其他一些方法会涉及更多。
您还可以考虑编写一个反射系统,以提供更快的方式来查找类型信息,这样您就可以得到类似这样的东西:
Derived* GetComponent (MetaData *TypeIWant)
{
if (componentlist[i]->Type() == TypeIWant)
//...
}
从长远来看,这将需要更多的工作,并且需要您自己做一些研究,但这可能是我所知道的唯一不需要使用字符串查找和“可怕”的 c++ 选项dynamic_cast 很多人都讨厌。
关于c++ - 使用模板制作类型安全的 C++ "component manager",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10592849/