C ++迭代某个子类的列表

时间:2013-11-03 12:44:43

标签: c++ list casting iterator subclass

我有两节课。超类是“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 ++很陌生,所以我不知道是否有更好的方法。

2 个答案:

答案 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");

这可能实际上是这段代码的真正瓶颈。