假设我有这样的伪代码:

bool conditionA = executeStepA();
if (conditionA){
    bool conditionB = executeStepB();
    if (conditionB){
        bool conditionC = executeStepC();
        if (conditionC){
            ...
        }
    }
}

executeThisFunctionInAnyCase();

函数executeStepX当且仅当前一个成功时执行。 在任何情况下,executeThisFunctionInAnyCase函数都应该在最后被调用。 我在编程方面是一个新手,所以很抱歉提出一个非常基本的问题:有没有一种方法(例如在C/ c++中)以代码易读性为代价,避免长if链产生那种“金字塔式代码”?

我知道如果我们可以跳过executeThisFunctionInAnyCase函数调用,代码可以简化为:

bool conditionA = executeStepA();
if (!conditionA) return;
bool conditionB = executeStepB();
if (!conditionB) return;
bool conditionC = executeStepC();
if (!conditionC) return;

但是约束是executeThisFunctionInAnyCase函数调用。 break语句可以以某种方式使用吗?


当前回答

在c++中(这个问题在C和c++中都有标记),如果你不能改变函数来使用异常,你仍然可以使用异常机制,如果你写一个像这样的小助手函数

struct function_failed {};
void attempt(bool retval)
{
  if (!retval)
    throw function_failed(); // or a more specific exception class
}

然后你的代码可以如下所示:

try
{
  attempt(executeStepA());
  attempt(executeStepB());
  attempt(executeStepC());
}
catch (function_failed)
{
  // -- this block intentionally left empty --
}

executeThisFunctionInAnyCase();

如果你喜欢花哨的语法,你可以通过显式强制转换来让它工作:

struct function_failed {};
struct attempt
{
  attempt(bool retval)
  {
    if (!retval)
      throw function_failed();
  }
};

然后您可以将代码编写为

try
{
  (attempt) executeStepA();
  (attempt) executeStepB();
  (attempt) executeStepC();
}
catch (function_failed)
{
  // -- this block intentionally left empty --
}

executeThisFunctionInAnyCase();

其他回答

把有条件的东西移到else中怎么样?

if (!(conditionA = executeStepA()){}
else if (!(conditionB = executeStepB()){}
else if (!(conditionC = executeStepC()){}
else if (!(conditionD = executeStepD()){}

这确实解决了缩进问题。

让执行函数在失败时抛出异常,而不是返回false。然后你的调用代码看起来像这样:

try {
    executeStepA();
    executeStepB();
    executeStepC();
}
catch (...)

当然,我假设在您最初的示例中,执行步骤只会在步骤内发生错误的情况下返回false ?

对于c++ 11及以上版本,一个很好的方法可能是实现一个类似D的作用域(退出)机制的作用域退出系统。

实现它的一种可能的方法是使用c++ 11 lambdas和一些helper宏:

template<typename F> struct ScopeExit 
{
    ScopeExit(F f) : fn(f) { }
    ~ScopeExit() 
    { 
         fn();
    }

    F fn;
};

template<typename F> ScopeExit<F> MakeScopeExit(F f) { return ScopeExit<F>(f); };

#define STR_APPEND2_HELPER(x, y) x##y
#define STR_APPEND2(x, y) STR_APPEND2_HELPER(x, y)

#define SCOPE_EXIT(code)\
    auto STR_APPEND2(scope_exit_, __LINE__) = MakeScopeExit([&](){ code })

这将允许你提前从函数返回,并确保你定义的任何清理代码总是在作用域退出时执行:

SCOPE_EXIT(
    delete pointerA;
    delete pointerB;
    close(fileC); );

if (!executeStepA())
    return;

if (!executeStepB())
    return;

if (!executeStepC())
    return;

宏实际上只是装饰。MakeScopeExit()可以直接使用。

while(executeStepA() && executeStepB() && executeStepC() && 0);
executeThisFunctionInAnyCase();

executeThisFunctionInAnyCase()必须在任何情况下执行,即使其他函数没有完成。

while语句:

while(executeStepA() && executeStepB() && executeStepC() && 0)

将执行所有的函数,不会循环,因为这是一个明确的错误语句。 也可以在退出前重试一定次数。

只做

if( executeStepA() && executeStepB() && executeStepC() )
{
    // ...
}
executeThisFunctionInAnyCase();

就是这么简单。


由于三次编辑都从根本上改变了问题(如果算上版本1的修订,则是四次),我包括了我正在回答的代码示例:

bool conditionA = executeStepA();
if (conditionA){
    bool conditionB = executeStepB();
    if (conditionB){
        bool conditionC = executeStepC();
        if (conditionC){
            ...
        }
    }
}

executeThisFunctionInAnyCase();