当代码流是这样的:

if(check())
{
  ...
  ...
  if(check())
  {
    ...
    ...
    if(check())
    {
      ...
      ...
    }
  }
}

我通常看到这种方法可以避免上述混乱的代码流:

do {
    if(!check()) break;
    ...
    ...
    if(!check()) break;
    ...
    ...
    if(!check()) break;
    ...
    ...
} while(0);

有什么更好的方法可以避免这种工作/黑客,从而使其成为更高级别(行业级别)的代码?

任何跳出盒子的建议都是欢迎的!


当前回答

如果你的代码有一个很长的If ..else If ..else语句块,你可以尝试在函子或函数指针的帮助下重写整个块。这可能并不总是正确的解决方案,但通常是正确的。

http://www.cprogramming.com/tutorial/functors-function-objects-in-c++.html

其他回答

如果你不需要在执行过程中引入局部变量,那么你通常可以将其平化:

if (check()) {
  doStuff();
}  
if (stillOk()) {
  doMoreStuff();
}
if (amIStillReallyOk()) {
  doEvenMore();
}

// edit 
doThingsAtEndAndReportErrorStatus()

如何移动if语句到一个额外的函数,产生一个数值或enum结果?

int ConditionCode (void) {
   if (condition1)
      return 1;
   if (condition2)
      return 2;
   ...
   return 0;
}


void MyFunc (void) {
   switch (ConditionCode ()) {
      case 1:
         ...
         break;

      case 2:
         ...
         break;

      ...

      default:
         ...
         break;
   }
}

也许就像这样

#define EVER ;;

for(EVER)
{
    if(!check()) break;
}

或者使用异常

try
{
    for(;;)
        if(!check()) throw 1;
}
catch()
{
}

使用异常还可以传递数据。

如果对所有错误使用相同的错误处理程序,并且每一步返回一个bool值指示成功:

if(
    DoSomething() &&
    DoSomethingElse() &&
    DoAThirdThing() )
{
    // do good condition action
}
else
{
    // handle error
}

(类似于tyzoid的回答,但条件是动作,&&防止在第一次失败后发生额外的动作。)

有些时候,使用goto实际上是正确的答案——至少对那些没有在宗教信仰中长大的人来说,“不管问题是什么,goto永远都不是答案”——这是其中的一个例子。

此代码使用了do{…}, (0);唯一的目的就是把一个傻瓜打扮成休息的样子。如果你打算使用goto,那就公开使用它。让代码更难阅读是没有意义的。

一种特殊的情况是当你有很多代码和相当复杂的条件时:

void func()
{
   setup of lots of stuff
   ...
   if (condition)
   {
      ... 
      ...
      if (!other condition)
      {
          ...
          if (another condition)
          {
              ... 
              if (yet another condition)
              {
                  ...
                  if (...)
                     ... 
              }
          }
      }
  .... 

  }
  finish up. 
}

没有如此复杂的逻辑,实际上可以更清楚地表明代码是正确的。

void func()
{
   setup of lots of stuff
   ...
   if (!condition)
   {
      goto finish;
   }
   ... 
   ...
   if (other condition)
   {
      goto finish;
   }
   ...
   if (!another condition)
   {
      goto finish;
   }
   ... 
   if (!yet another condition)
   {
      goto finish;
   }
   ... 
   .... 
   if (...)
         ...    // No need to use goto here. 
 finish:
   finish up. 
}

编辑:澄清一下,我绝不是建议使用goto作为通用解决方案。但在某些情况下,goto是比其他解决方案更好的解决方案。

例如,想象一下,我们正在收集一些数据,测试的不同条件是某种“这是正在收集的数据的结束”——这取决于某种“继续/结束”标记,这些标记根据您在数据流中的位置而变化。

现在,当我们完成之后,我们需要将数据保存到一个文件中。

是的,通常有其他解决方案可以提供合理的解决方案,但并不总是如此。