c++ - 在 C++ 中使用嵌套开关是一种好习惯吗?有没有其他方法可以避免这种情况?

标签 c++ methods

目前我有一个函数,它有两个枚举类型的参数,该函数需要比较两者并执行特定任务 示例:

 void set_Test_Status(Tests TestName, Status TestStatus)
 {
    switch(TestName)
    {
         case Tests::Test1:
              {
                 switch(TestStatus)
                 {
                     case TestStatus::St1:
                     //Rest of Code
                 }
              }
           //Rest of Code
    }
 }

这是一个好的编程习惯吗?或者是否有任何我应该注意的替代方法或编码风格?谢谢!

编辑: 最后经过反复试验,我做到了。首先,我看到了每个枚举中的最大和最小项目,在我的例子中,TestName 是 6,TestStatus 有 3。我创建了 3 个函数 setStatusRunning(Tests TestName)、setStatusSelected(Tests TestName) 和 setStatusFinished(Tests TestName),在 set_Test_status 中,使用 switch (TestName) 我检查应调用哪个函数,然后调用适当的函数。我必须首先设置 set_Test_Status 的原因是为了方便其他类,因为我将 set_Test_Status 设置为公开,而其他 3 个设置为私有(private)。

最佳答案

这确实是一个见仁见智的问题,因为嵌套的 switch 语句是有效的 c++ 代码。有些人可能对此没有问题,而另一些人可能会争辩说它可能会造成混淆。

我的建议是这样;如果 case 语句中的代码块很短,例如 1-2 行,并且它们很容易阅读和遵循,那么它应该没有问题。但是,如果代码非常繁琐并且嵌套的 switch 语句超过 50 到 100 多行,那么我建议改进您的代码并从中创建函数。

例子:

// should be okay

unsigned int outerSwitch = someValue(); 
unsigned int innerSwitch = someOtherValue();
switch ( outerSwitch ) {
    case 1: {
        switch ( innerSwitch ) {
            case 1 : {
                // 1 or 2 lines okay;  
            } 
            case 2 : {
                // 1 or 2 lines okay;
            }
            case 3 : {
                // 1 or 2 lines okay;
            }
            default : {

            }
        } // inner switch when outer switch case = 1
    }
    case 2: {
          // Same as case 1
    }
    case 3: {
          // Same as case 1
    }
    default: {

    }
} // outer switch

但是正如您在上面看到的,外部和内部只有 3 个案例;它很快就变得很长,我什至还没有全部展开。所以这可能是不受欢迎的。

您可以像其他人建议的那样使用单个开关调用该开关的特定函数,然后在该函数中它有自己的开关语句,如下所示:

unsigned int someFuncA( unsigned int someVal ) {
    switch ( someVal ) {
        case 1 : {
            // do this
            // return that;   
        }
        case 2: {
            // ... etc.
        }
    } // switch
} 

unsigned int someFuncB( int someVal ) {
    // similar to someFuncA();
}

unsigned int someFuncC( int someVal ) {
    // similar to someFuncA();
}

unsigned int switchValue = someValue();
unsigned int innerValue = someOtherFunction();
unsigned int temp = 0;
switch( switchValue ) {
    case 1 : {
        temp = someFuncA( innerValue );
        // either return temp, break, continue, or fall through
    }
    case 2 : {
        temp = someFuncB( innerValue );
        // same as above
    case 3 : {
        temp = someFuncC( innerValue );
        // same as above
    }
    default : {
        // default stuff here
    }   
} // switch

比较这两个版本,您会发现第二个版本比第一个版本更容易阅读,也没有那么繁琐。是的,第一个版本是有效的合法 C++ 代码,但由于它可以轻松快速地变得多么困惑,所以不受欢迎。因此,无论何时何地;将该代码转换为一个函数,该函数旨在只做一件事。

编辑

另一种可能性是设计特定的函数来完成一项任务,正如您所说,您的函数采用 2 个不同的枚举值,您可以查找旨在采用位标志的函数的概念。您会在 Windows 编程和 OpenGL 中看到相当多的此类代码。

另一种选择是:考虑到您有一个外部控制开关和一个内部控制开关。即使您有多个案例,每个案例都是独立的,具有特定的唯一 ID。内部开关盒也是如此。了解这一点后,您可以使用 std::multimap<unsigned, unsigned> testCases 创建组合事件中所有语句的关联映射。使用这个查找表,您可以将它放在一个语句中,并对每个映射条目进行独立的函数调用。 cppreference : std::multimap

您的 map 可能如下所示:

testCases[1][1];
testCases[1][2];
testCases[1][3];
testCases[2][1];
testCases[2][2];
testCases[2][3];
testCases[3][1];
testCases[3][2];
testCases[3][3];

map 的每个索引是您要执行的逻辑或计算。

关于c++ - 在 C++ 中使用嵌套开关是一种好习惯吗?有没有其他方法可以避免这种情况?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49252299/

相关文章:

c++ - 如何更改要反转的 std::map 的顺序?

c++ - C++中的前缀匹配

java - 使用方法和多个类的一副纸牌

javascript - 如何将 JavaScript 回调设置为外部(包装)对象的方法?

Python 3 绑定(bind)方法订阅

c++ - 类有虚方法但非虚析构函数C++

c++ - 没有 OpenGL 的纹理映射

c++ - 使用SIMD指令的平行二项式系数

c++ - 可自定义常量的基类参数与纯虚函数

methods - 在 Racket 方法名称中使用 "?"是一种不好的做法吗?