在switch case中声明变量(子类别的枚举) - 什么是替代?

时间:2016-11-21 08:31:30

标签: c++ c++11 switch-statement

我有一个包含多种turret类型的游戏,每种类型都可以简单地用枚号表示。

当存在turret的子类别时会出现重复代码问题。

我目前的代码如下: -

switch(type_of_turret){
    //category : SHOOTER
    case SHOOTER_FIRE :
    case SHOOTER_ICE :
    {
        float temperator=0;
        switch(type_of_turret){               //duplicate switch case
            case SHOOTER_FIRE : temperator=1000;     break;
            case SHOOTER_ICE :  temperator=-1000;   break;
        }
        temperator=sinWave(temperator,time); //(Edit) an example of calculation
        shoot(rigidBody,temperator);
    }break;
    //category : PROPULSION
    ......
    break;
}

type_of_turret(10到20)的类型并不多,但重复对我来说已经很糟糕了。

如果我可以在交换机内声明变量(但不在内部情况下),那就太好了: -

switch(type_of_turret){
    float temperator=0;                    //neat but wrong syntax
    case SHOOTER_FIRE : temperator=1000;   /*break?*/  //neat 
    case SHOOTER_ICE : temperator=-1000;   /*break?*/  //neat
        temperator=sinWave(temperator,time);  //(Edit) just an example 
        shoot(rigidBody,temperator);       //neat
    break;
    ....
    break;
}

问题

如何使代码更整洁?
具体来说,我如何模仿" switch-case"中的声明变量?行为?

我糟糕的解决方案

为每个类别创建类,例如来自Shooter的{​​{1}}和Propulsion  然后使用枚举或更多派生类创建Turret的子类别 缺点:引入了不必要的复杂性,性能可能会降低(虚拟功能)

编辑(另一个缺点):它打破"无方法宗教"我的实体组件系统的内容如下: -

  

你会发现代理组件的方法都应该存在于系统内部,而不是组件

http://t-machine.org/index.php/2007/12/22/entity-systems-are-the-future-of-mmog-development-part-3/

参考

stackoverflow上有一些类似的问题,例如: Why can't variables be declared in a switch statement?,但没有人讨论替代方法是什么。

2 个答案:

答案 0 :(得分:1)

您的问题实际上并没有为某些(但不是全部)交换机案例调用公共变量。相反,显而易见的解决方案是从每个shoot()案例中简单SHOOTER

enum struct shooter { fire, ice };
inline int temperature(shooter);

switch(type_of_turret){
case SHOOTER_FIRE: shoot(rigidBody, temperature(shooter::fire));
  break;
case SHOOTER_ICE: shoot(rigidBody, temperature(shooter::ice));
  break;
......
}

答案 1 :(得分:1)

正如我在评论中所说,不要害怕具有虚函数的多态类。例如,我会在每个炮塔子类中定义一个虚拟shoot()函数来处理温度,甚至虚拟MyTemp()

class BaseTurretT
{   
    virtual int MyTemp() = 0;
    public:
    virtual void shootAt(RigidBodyT &rb)
    {
        // default implementation, may be overriden
        shoot(rb, MyTemp());
    }
    // ...
};

class HotTurretT: public BaseTurretT
{
    int MyTemp() { return 1000; }
    // ...
};

class ColdTurretT: public BaseTurretT
{
    int MyTemp() { return -1000; }
    // ...
};        

// more turrets in the future.

通过这些定义,您的整个交换机将折叠为一行。假设我们有一个指向基础炮塔的指针向量。指向的对象是各种派生炮塔,但使用代码并不知道并且不关心:

RigidBodyT rb; 
vector<BaseTurretT *> turrets;
// ... 
for(BaseTurretT *turret: turrets)
{
    turret->shootAt(rb);    // no switch. No idea which turret type.
}

这种设计最好的一点是它的可维护性。如果你想在未来添加更多的炮塔(并观察游戏进化的方式,这似乎是一个安全的赌注),你不必重新访问你使用炮塔的地方。你只需要添加一个新的类,所有现有的代码都会自行处理。