基本上,我有两个类,Spatial和Node,继承自IEntity; IEntity是一个抽象类(接口)。我将实体对象指针存储在SceneGraph类的std :: vector中,如std::vector<IEntity*>
所以为了区分Spatials和Nodes,我首先有了想法
if(!dynamic_cast<Node*>(myEntity)) // equals nullptr, cast failed
{
BOOST_LOG_TRIVIAL(info) << "It is a node !";
}
但是这段代码适用于高性能引擎,而且我在一秒钟内无法负担数千/百万的动态转换调用;那么你会建议将空间指针和节点区分为低位而没有任何错误(以最快的方式)? PS。我知道不建议将指针存储在stl容器中,但这是围绕imo的最好方法。
答案 0 :(得分:3)
首先,在这种情况下不得不贬低是一个明显的迹象,表明糟糕的设计打破了利斯科夫的原则。要在OOP域中修复它,而不是向下转换,您应该为每个IEntity
对象调用某个虚拟函数,然后对Node
执行不同的操作,为Spatial
执行不同的操作。< / p>
其次,如果你的目标是性能,你应该放弃性能关键代码中的OOP。即没有调用虚函数。您还应该尝试尽可能多地利用内存缓存,因为对非缓存数据的内存访问通常是大多数性能关键代码的瓶颈。怎么做?谷歌的“数据驱动设计”或“面向数据的编程”。这通常使用称为“实体组件系统”的东西来实现,通常在计算机游戏中。在您的情况下,您可能需要将Nodes
和Spatials
分隔在不相关的向量中,而不是通过引用或指针IEntity
而是按值分隔(使用vector<Node>
和{{ 1}}而不是vector<Spatial>
)然后线性地或以可预测/常规顺序遍历它(以利用专业数据预取)。这将为您提供最快的速度。并且可能只是在那之后你应该从一些算法微调开始......这是典型的场景,所以我认为这也是你的情况。
顺便说一下。除了性能(如你的情况),在STL容器中存储指针没有任何错误。还是有吗?
更新:正如您在下面提到的,出于某些算法原因,您可能需要将对象保留在树结构中。在这种情况下,我关于按值保存容器中的对象的建议可能不是那么有用或直接实现。无论如何,在任何情况下,你必须首先描述我们的代码,然后尝试优化和摆弄缓存等。但是我的第一个关于错误设计的注释表明需要向下转换仍然有效。 :)