目前我的函数有两个枚举类型的参数,该函数需要比较两者并执行特定任务 例如:
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设为public而另外3个为private。
答案 0 :(得分:3)
由于嵌套的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 ++代码,但由于它可以轻松快速地获得多么混乱,因此不赞成。所以,你可以在哪里;将该代码转换为专门用于完成这一任务的函数。
修改强>
另一种可能性是设计特定的函数来完成一项任务,正如你所说的,你的函数有两个不同的枚举值,你可以查找设计用于取位标志的函数的概念。你会在Windows编程和OpenGL中看到这种代码。
另一种选择是:考虑到你有一个外部控制开关和内部控制开关。即使您有多个案例,每个案例都是独立的,具有特定的唯一ID。对于内部开关情况也是如此。知道了这一点,您可以使用std::multimap<unsigned, unsigned> testCases
创建组合事务中所有语句的关联映射,并使用此查找表,您可以将它放在一个语句中,并对每个映射条目进行独立的函数调用。 cppreference : std::multimap
您的地图可能如下所示:
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];
地图的每个索引都是您要执行的逻辑或计算。
答案 1 :(得分:2)
对于阅读代码的人来说,这可能会让人感到困惑 - 缩进有所帮助,但在case和switch语句的开始和结束时仍然很难遵循。大多数IDE都支持查找匹配的括号,但找到匹配的中断通常不是一件事,所以甚至很难看到case语句的结束位置。 (技术上的情况并没有定义范围,而大括号也是如此,所以它甚至没有结束。)
如果你的牙箍未对齐或意外不匹配,你可能会发生奇怪的事情。像Ada这样的语言尝试使用强类型的英语说明符来防止这种情况。
如果你正在做很多子开关,我会把它们放到另一个函数中并用它需要的信息调用它,然后你可以在方法里面做一个switch语句,它更模块化,单独的范围和清楚的东西正在继续。
答案 2 :(得分:1)
保持代码简洁的一个好习惯是在函数中只做一件事。使用开关已经是一种气味,你的功能将会做不同的事情。这完全取决于您的具体情况。
要注意的一件事是:在一个班级中管理所有这些案例是否一致。如果每个可能性都有一个类,接口强制实现一个函数,而不是在switch case中做所有的可能性。
如果你想保留开关,一个好的做法是不要在开关之外放置代码。每个案例只调用一个函数。这将使东西更具可读性。
最后,您使用的是所有案例吗?如果不是,只需实现所需的值对,就可以更清晰地编写代码:
if(TestName == Tests::Test1 && TestStatus == TestStatus::St1)
{
doThing();
}
总结:
这可能是一种气味,你的代码需要在更多的类中拆分,每个类只有一个责任(如果和/或太多的开关是太多的标志)。如果您确定需要开关,请尽可能简单明了