C++ C-do{..}while(0);是否可以从代码中删除,但不包括嵌套用法?
do{…}while(0)强> do{}while(0)的用法在我的编码中使用strong>是因为我不想使用长if else嵌套条件语句。我最终在失败时中断并退出循环,并保证我的函数至少会被遍历一次 现在,代码警告工具出现了问题,我在使用do{…}while(0)时收到了警告强> nested if(){}else{}的使用可读性较差,复杂度较高。让代码有死代码 如果我排除嵌套if(){}else{}和do{}while(0),我们是否留下了一些其他方法使代码具有可读性和可理解的逻辑C++ C-do{..}while(0);是否可以从代码中删除,但不包括嵌套用法?,c++,c,C++,C,do{…}while(0) do{}while(0)的用法是因为我不想使用长if else嵌套条件语句。我最终在失败时中断并退出循环,并保证我的函数至少会被遍历一次 现在,代码警告工具出现了问题,我在使用do{…}while(0)时收到了警告 nested if(){}else{}的使用可读性较差,复杂度较高。让代码有死代码 如果我排除嵌套if(){}else{}和do{}while(0),我们是否留下了一些其他方法使代码具有可读性和可理解的逻辑 if(status_of_funcA_ok !=
if(status_of_funcA_ok != funcA())
{ //failure}
else if (status_of_funcB_ok != funcB())
{//failure}
else if (status_of_funcC_ok != funcC())
else
{//Great}
do{
if(status_of_funcA_ok != funcA())
break;
if (status_of_funcB_ok != funcB())
break;
if (status_of_funcC_ok != funcC())
break;
}while(0);
您可以使用
goto
而不是do{},同时(0)
和break
。这是不可读的,但也不是好的做法。我认为,对于每一种具体情况,都有一种更好的方法来避免深入的if/else结构。例如,有时使用函数调用可以帮助:
例如,而不是:
if(status_of_funcA_ok != funcA())
{ //failure}
else if (status_of_funcB_ok != funcB())
{//failure}
else if (status_of_funcC_ok != funcC())
else
{//Great}
你可以写:
if (check_funcs() == 0) {
great();
}
int check_funcs() {
if (status_of_funcA_ok != funcA())
return -1;
if (if(status_of_funcB_ok != funcB()))
return -2;
if (if(status_of_funcC_ok != funcC()))
return -3;
return 0; /* great */
}
有时,您可以使用exit()
<>也可以,在C++中,可以使用<代码>()/<代码>和<代码>尝试/捕获< /代码>:
try {
/* */
throw (this error);
/* */
throw (that error);
} catch (this error) {
} catch (that error) {
}
如果有更多条件要检查,请避免使用
If{}else{},
最佳实践是用嵌套的if-else语句替换if-else条件,但我认为使用do{..}while(0);作为替代者,情况会更糟。这是非常非常规的,任何阅读它的人都不会真正将它与if-else语句联系起来 为了使嵌套的if-else语句更具可读性,您可以做一些事情。以下是一些建议:
将
do while{0}
循环的完整逻辑移到一个函数中,并将break
替换为return
。并调用函数,而不是循环
do
PS:您似乎不需要函数的返回值,但您可以使用它来获得哪个函数成功的线索。我也在使用此模式,对于那些想知道的人,这里有一个抽象示例:
do // while(0) for break
{
state1 = 0;
if (cond1())
{
if (cond2())
break;
state1 = opA();
}
if (cond3() || state1 && state1->cond4())
break;
...
Triumph(state1, ...);
// often here: return
}
Failure(state1, ...);
我认为这在以下情况下是有效的:
- 你有一个很长的序列(比如说,>~6个条件)
- 条件很复杂,您使用/建立了重要状态,因此无法 将元素分离为函数
- 您处于异常不友好的环境中,或者您的
-ing代码路径为 事实上并非例外中断
while(a1!=a1)
而不是while(a1!=a2)
[/edit]
分解成函数,将状态移动到类中这将把上述代码转换为:
struct Garbler
{
State1 state1;
bool Step1()
{
state1 = 0;
if (cond1())
{
if (cond2())
return false;
state1 = opA();
}
return true;
}
bool Step2()
{
return cond3() || state1 && state1->cond4();
}
..
void Run()
{
if (Step1() && Step2() && ... && Step23())
Triumph(state1, ...);
else
Failure(state1, ...);
}
}
这可以说是可读性较差,更糟糕的是,您将序列分开,这可能会导致一个非常可疑的类(在该类中,成员可能仅按特定顺序调用)
这可能允许将中断转换为早期回报,这是更可接受的:
state1 = 0;
ScopeGuard gFailure = MakeGuard(&Failure, ByRef(state1), ...);
if (cond1())
{
if (cond2())
return;
state1 = opA();
}
if (cond3() || state1 && state1->cond4())
return;
// everything went ok, we can dismiss the scopeguard
gFailure.Dismiss();
Triumph(state1, ...);
它们可以更优雅地用C++0x编写,保留流,但解决方案也没有那么灵活,例如当
Failure()
无法轻松地隔离到单个函数中时 对这个问题解释得不多,现在已经接近了(你能举一个具体的例子说明你的plz代码的一部分吗?也许可以重写不同的代码。编译器可以警告他们喜欢的任何事情;在所有情况下避免所有警告是不切实际的。大多数警告都很重要,但如果你知道你在做什么(即,在这种情况下,你实际上比编译器更了解),你可以忽略它们。我举了一个例子!希望它能更容易理解。throw()和catch()应该只保留在特殊情况下(例外)。将它们用作流控制结构是不好的做法。谢谢你的回答。我认为goto/return是一个更好的选择,但是..愚蠢的讨厌的工具也将这些东西作为警告。由于多次中断,goto的使用。由于我使用的是C,throw和catch将不适用,我可以使用sub-helper函数指针,它将在一个循环中结束每个条件,我可以运行这些函数。但是对于或多或少4到5个条件检查的小函数,这种方法在嵌入式编程中可以接受吗?这是一个严重的疑问,因为我对这个行业非常陌生。@bancsy:原则上它们是流控制结构,如果不控制流,你还能用它们吗?它们应该用于转义没有意义继续的代码路径,是否会发生这种情况取决于您的情况。通常,您可以使用一个函数来检查导致错误的前提条件