简体   繁体   English

C ++遍历某个子类的列表

[英]C++ Iterating over a list of a certain subclass

I have two classes. 我有两节课。 The superclass is a "Component" class, and the subclass is a "Transform" class. 超类是“ Component”类,而子类是“ Transform”类。

The framework I'm using has a function that returns a list of components of a certain type. 我正在使用的框架具有返回特定类型的组件列表的功能。 However, the list will return them as Component, since the type isn't restricted to a specific subclass (however it's the way I'm using it). 但是,该列表会将它们作为Component返回,因为类型不限于特定的子类(但是这是我使用它的方式)。

So, in the following scenario, I know that all the returned components will be of the Transform subclass. 因此,在以下情况下,我知道所有返回的组件都是Transform子类的。 What I'm doing is I'm iterating over the list and then casting each component to Transform. 我正在做的是遍历列表,然后将每个组件转换为Transform。 Here is my code: 这是我的代码:

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 ;
}

How efficient is this? 这有多有效? I'm quite new to C++, so I have no idea if there's a better way of doing this. 我对C ++还是很陌生,所以我不知道是否有更好的方法可以做到这一点。

This isn't a good design, your compiler should generate a warning in this case. 这不是一个好的设计,在这种情况下,编译器应生成警告。 Normally, you should upcast your pointer using dynamic_cast. 通常,您应该使用dynamic_cast向上转换指针。 This cast has some runtime cost - aproximately the same as virtual method call but it will generate exception if you try to cast incompatible pointers. 这种强制转换会产生一些运行时成本-与虚拟方法调用几乎相同,但是如果您尝试强制转换不兼容的指针,它将产生异常。 Try to redesign your app to eliminate this code. 尝试重新设计您的应用程序以消除此代码。 You should only call virtual methods of the Component class, you shouldn't cast pointer to Component to pointer to Transform . 您应该只调用Component类的虚拟方法,而不应该将Component的指针TransformTransform指针。 This thing indicate bad design. 这东西表明设计不好。

One possible desigion is to make getComponents a template method to eliminate cast: 一种可能的设计是使getComponents成为消除强制转换的模板方法:

template<class T>
list<T*> getComponents(Player* player, std::string name) {
    ...
}

or maybe just this: 或仅仅是这样:

list<Transform*> getTransfromComponents(Player* player) {...}

In a case when you can't refactor this code, you can always transform your list: 如果您无法重构此代码,则可以随时转换列表:

    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);

The std::list is usually implemented as double-linked list, which means that elements are scattered through the memory, which means that iterating through it is slow. std::list通常实现为双链表,这意味着元素分散在内存中,这意味着迭代很慢。 Check: Why is it so slow iterating over a big std::list? 检查: 为什么在一个大std :: list上迭代这么慢?

But what I would worry more about is the use of reflection: 但是我更担心的是反射的使用:

objectManager->getComponents(player,"Transform");

that might actually be the real bottleneck of this piece of code. 这实际上可能是这段代码的真正瓶颈。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM