Switch Case Statement C ++编码风格

时间:2014-01-10 08:59:51

标签: c++ coding-style

我使用枚举在类型系统中的类型之间切换,如:

enum FruitType {
    APPLE;
    PEAR;
    CHERRY;
    ORANGE;
    BANANA;
    .
    .
    .
}

现在我有几个函数只对子集有效(在函数之间有所不同),并且应该为所有其他函数抛出异常。
这可能是个人品味的问题,但您认为以下哪一项最容易阅读/可维护/最不容易出错? 或者是否有一个我想不到的更优雅的版本?

选项1:

switch(o.fruitType)
{
    case APPLE:
    case PEAR:
    case ORANGE:
    {
        // do all the stuff i want to do
        string ret;
        // ...
        function(o,ret);
        return ret;     
    }
    default:
        throw InvalidFunctionParameterException();
}

选项2:

if(o.fruitType == APPLE || o.fruitType == PEAR || o.fruitType == ORANGE)
{
    // do all the stuff i want to do
    string ret;
    // ...
    function(o,ret);
    return ret;     
}
else
{
    throw InvalidFunctionParameterException();
}

选项3:

switch(o.fruitType)
{
    case APPLE:
    case PEAR:
    case ORANGE:
        break;
    default:
        throw InvalidFunctionParameterException();
}

// do all the stuff i want to do
string ret;
// ...
function(o,ret);
return ret;         

4 个答案:

答案 0 :(得分:1)

编程风格。这是非常个人化的,每个人都有自己的看法。

我发现最好尝试做“什么表达我最好的意思”。换句话说,哪种写入方式代表了您期望的流程,以及您期望的行为,基于“这就是我想要发生的事情”(例如,需求规范告诉您代码应该是什么)做)。

我个人认为第三个最难读,因为它依赖于你发现throw中间的switch为关键。如果你在switch(或if)中放入其他“do stuff”功能,那么“我们为这些事情做这件事,其他任何事情都是错误的”就更清楚了。

我希望编译器最终会生成更多或更少的等效代码,可能会使switch的代码略好于if,因为switch通常用表,if或多或少必须遵循你所写的内容(条件短路是这里的一个重要特征)。

当然,您还必须考虑项目/公司编码样式指南,这可能有关于“如何编写switch语句”的说法。

答案 1 :(得分:1)

  

或者是否有一个我想不到的更优雅的版本?

将其实现为具有虚函数的类层次结构:

// client code:
o.processByFruitType();

class Fruit {
    virtual string processByFruitType() {
        throw InvalidFunctionParameterException();
    }
};

// fruit implementations:
class Apple: public Fruit {
    virtual string processByFruitType() override {
        // do all the stuff i want to do
        string ret;
        // ...
        function(*this,ret);
        return ret;     
    }
};

其他专业化也遵循类似的实施方式。

答案 2 :(得分:1)

我同意,这是个人问题,但我相信,第一个选项是最具可读性的。

我也在情境中使用它,当函数应该对某些值做出反应时,明确地不应该对其他人做出反应

switch(o.fruitType)
{
    case APPLE:
    {
        DoSomethingWithApple();
        break;
    }
    case PEAR:
    {
        DoSomethingWithPear();
        break;
    }
    case ORANGE:
    {
        DoSomethingWithOrange();
        break;
    }
    default:
    {
        // Explicitly left empty
    }
}

我留下这个“Explicitly left empty”评论,以便我的代码的未来读者知道,如果遇到其他值,我明确希望这段代码什么都不做。优化器会将此代码删除,因此不会影响性能。

答案 3 :(得分:-1)

  

或者是否有一个我想不到的更优雅的版本?

如果你在代码中执行了大量操作,那么编写支持这样的断言的函数/宏:

PARAM_ASSERT(o.fruitType == APPLE || o.fruitType == PEAR || o.fruitType == ORANGE);

// do all the stuff i want to do
string ret;
// ...
function(o,ret);
return ret;

实施可能含糊不清:

#define PARAM_ASSERT(X) \
    do { \
        if (!(X)) throw InvalidFunctionParameterException(); \
    } while (false)

使用宏,您可以在不触及客户端代码的情况下保留使用__LINE____FILE__#X(条件的字符串化版本)等来丰富异常的自由。 ...