我有两节课。超类是“Component”类,子类是“Transform”类。
我正在使用的框架有一个函数,它返回某种类型的组件列表。但是,列表将它们作为Component返回,因为类型不限于特定的子类(但这是我使用它的方式)。
因此,在以下场景中,我知道所有返回的组件都是Transform子类。我正在做的是我在列表上进行迭代,然后将每个组件转换为Transform。这是我的代码:
std::list<Cistron::Component*,std::allocator<Cistron::Component*>> playerTransforms = objectManager->getComponents(player,"Transform");
std::list<Cistron::Component*>::iterator playerComponentIterator = playerTransforms.begin();
for (playerComponentIterator; playerComponentIterator != playerTransforms.end(); playerComponentIterator++)
{
Transform *tmpTransform = static_cast<Transform*> (*playerComponentIterator);
std::cout << tmpTransform->x ;
std::cout << tmpTransform->y ;
}
这有多高效?我对C ++很陌生,所以我不知道是否有更好的方法。
答案 0 :(得分:2)
这不是一个好的设计,在这种情况下你的编译器应该生成一个警告。通常,您应该使用dynamic_cast来转发指针。此转换具有一些运行时成本 - 与虚拟方法调用大致相同,但如果您尝试转换不兼容的指针,它将生成异常。
尝试重新设计您的应用以消除此代码。您应该只调用Component
类的虚方法,不应将指向Component
的指针指向Transform
。这件事表明设计不好。
一种可能的设计是使getComponents
模板方法消除强制转换:
template<class T>
list<T*> getComponents(Player* player, std::string name) {
...
}
或者只是这个:
list<Transform*> getTransfromComponents(Player* player) {...}
如果您无法重构此代码,您可以随时转换列表:
list<Component*> rlist = ...
list<Transform*> llist;
// Upcast all
transform(rlist.begin(),
rlist.end(),
back_inserter(llist),
[](Component* r) {
return dynamic_cast<Transform*>(r);
});
// Remove all null values
llist.remove(nullptr);
答案 1 :(得分:1)
std::list
通常实现为双链表,这意味着元素通过内存分散,这意味着迭代它很慢。检查:Why is it so slow iterating over a big std::list?
但我更担心的是使用反射:
objectManager->getComponents(player,"Transform");
这可能实际上是这段代码的真正瓶颈。