【问题标题】:C++ how to loop through different typesC++如何循环不同类型
【发布时间】:2014-07-16 18:36:01
【问题描述】:

假设我有一个Light 类,还有SpotLightPointLightDirectionalLight,它们继承自Light

我有一张这样的灯光地图:std::map<std::string, Light*> LightMap;

我想像这样为每种类型迭代这张地图:

for ( /* each SpotLight* in LightMap */ ) { ... }

for ( /* each PointLight* in LightMap */) { ... }

等等……

我该怎么做?

【问题讨论】:

  • 听起来像是虚拟函数可以帮助解决的问题。
  • @chris 是的。我就是这么想的。在某些情况下这可能行不通,但通常一个循环调用一个在每个子类中具有不同行为的单个虚函数听起来像是要走的路……
  • 如果这是在迭代时需要快速的东西,那么我会将每种类型保留在自己的指针数组中。或者,如果您可以在一个循环中处理所有灯光类型,请使用虚拟函数并循环一次。
  • 我想从这些类中检索数据,例如我想要 PointLight 的位置和 DirectionalLights 的方向,PointLight 没有方向,DirectionalLight 没有位置等。我是现在犹豫不决,我想我会使用单独的地图。
  • 不要创建单独的地图,而是看高

标签: c++ inheritance iterator iteration stdmap


【解决方案1】:

你不能,你必须遍历每个项目并转换为你想要的类类型。

for(std::map<std::string, Light*>::iterator iter = m.begin(); iter != m.end(); iter++)
{
    if (dynamic_cast<SpotLight*>(*iter))
    {
    }
}

为避免使用动态投射,您还可以向 Light 类添加函数,例如“IsSpotLight”,它可以由 SpotLight 类重载以返回 true,等等。

您还可以为每种类型的灯光制作单独的贴图,因此如果您只需要聚光灯,请使用 SpotLightMap 贴图。

【讨论】:

    【解决方案2】:

    您可以使用dynamic_cast 和多态基类来确定您要处理的光类型:

    #include <map>
    #include <string>
    #include <iostream>
    
    class Light { public: virtual ~Light(){} }; // Light is polymorphic
    class SpotLight : public Light {};
    class PointLight : public Light {};
    class DirectionalLight : public Light {};
    
    
    int main() {
        using namespace std;
        map<string, Light*> lightmap;
    
        for (const auto& light : lightmap) {
            if (SpotLight* spot = dynamic_cast<SpotLight*>(light.second))
                cout << light.first << " is a spot light" << endl;
            else if (PointLight* point = dynamic_cast<PointLight*>(light.second))
                cout << light.first << " is a point light" << endl;
            else if (DirectionalLight* point = dynamic_cast<DirectionalLight*>(light.second))
                cout << light.first << " is a directional light" << endl;
            else
                cout << light.first << " is an unknown light" << endl;
        }
    }
    

    【讨论】:

      【解决方案3】:

      我已经编写了一些代码来解决您的要求。

      class Light {
          typedef enum {SpotLight, PointLight, DirectionalLight} LightTypeT;
          LightTypeT GetLightType() = 0;
      };
      
      class SpotLight : public Light {
          LightTypeT GetLightType() { return SpotLight; }
      };
      
      
      class PointLight : public Light {
          LightTypeT GetLightType() { return PointLight; }
      };
      
      
      class DirectionalLight : public Light {
          LightTypeT GetLightType() { return DirectionalLight; }
      };
      
      typedef std::map<std::string, Light*> LightMapT;
      
      LightMapT::iterator be = light_map.begin(),
                          en = light_map.end();
      
      for (; be != en; be++)
      {
          Light * m_light = (*be).second;
          switch (m_light->GetLightType())
          {
              case SpotLight :
                  {
                       // It is SpotLight
                       break;
                  }
              case PointLight :
                  {
                      // It is PointLight
                      break;
                  }
      
              case DirectionalLight :
                  {
                      // It is DirectionalLight
                      break;
                  }
           }
      }
      

      如果它不能解决您的问题,请告诉我。我们会努力的

      【讨论】:

        【解决方案4】:

        类似的东西呢

        for ( /*each Light* lit in LightMap*/)
        {
            //if lit is instance of Spotlight, do something
        
        }
        
        for ( /*each Light* lit in LightMap*/)
        {
            //if lit is instance of PointLight, do something
        
        }
        

        有关instanceof 的C++ 版本,请参阅here

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-05-30
          • 2017-11-02
          • 1970-01-01
          • 2014-10-17
          • 2023-03-29
          • 1970-01-01
          • 2010-12-25
          • 2021-01-25
          相关资源
          最近更新 更多