假设我有这样的伪代码:

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语句可以以某种方式使用吗?


当前回答

你可以把所有的if条件,按照你想要的格式放在它们自己的函数中,返回执行executeThisFunctionInAnyCase()函数。

从OP中的基本示例来看,条件测试和执行可以这样分离;

void InitialSteps()
{
  bool conditionA = executeStepA();
  if (!conditionA)
    return;
  bool conditionB = executeStepB();
  if (!conditionB)
    return;
  bool conditionC = executeStepC();
  if (!conditionC)
    return;
}

然后被这样称呼;

InitialSteps();
executeThisFunctionInAnyCase();

如果c++ 11 lambda是可用的(OP中没有c++ 11标记,但它们可能仍然是一个选项),那么我们可以放弃单独的函数,并将其包装为lambda。

// Capture by reference (variable access may be required)
auto initialSteps = [&]() {
  // any additional code
  bool conditionA = executeStepA();
  if (!conditionA)
    return;
  // any additional code
  bool conditionB = executeStepB();
  if (!conditionB)
    return;
  // any additional code
  bool conditionC = executeStepC();
  if (!conditionC)
    return;
};

initialSteps();
executeThisFunctionInAnyCase();

其他回答

As @Jefffrey said, you can use the conditional short-circuit feature in almost every language, I personally dislike conditional statements with more than 2 condition (more than a single && or ||), just a matter of style. This code does the same (and probably would compile the same) and it looks a bit cleaner to me. You don't need curly braces, breaks, returns, functions, lambdas (only c++11), objects, etc. as long as every function in executeStepX() returns a value that can be cast to true if the next statement is to be executed or false otherwise.

if (executeStepA())
 if (executeStepB())
  if (executeStepC())
   //...
    if (executeStepN()); // <-- note the ';'

executeThisFunctionInAnyCase();

任何时候,任何函数返回false,都不会调用下一个函数。

我喜欢@Mayerz的答案,因为你可以在运行时改变要调用的函数(以及它们的顺序)。这有点像观察者模式,其中有一组订阅者(函数、对象等),只要满足给定的任意条件,就会调用和执行这些订阅者。在许多情况下,这可能是一个过度杀戮,所以明智地使用它:)

代码中的IF/ELSE链不是语言的问题,而是程序设计的问题。如果你能够重构或重写你的程序,我建议你在Design Patterns (http://sourcemaking.com/design_patterns)中寻找更好的解决方案。

通常,当您在代码中看到大量IF & else时,就有机会实现策略设计模式(http://sourcemaking.com/design_patterns/strategy/c-sharp-dot-net)或其他模式的组合。

我确信有替代方案来编写一长串if/else,但我怀疑它们除了对你来说看起来很漂亮之外不会改变任何东西(然而,情人眼里出佳人仍然适用于代码:-))。你应该关心这样的事情(6个月后,当我有一个新的条件,我不记得关于这个代码的任何事情,我是否能够轻松地添加它?)或者如果链发生变化,我将如何快速和无错误地实现它)

因为你也有……代码块…]在执行之间,我猜你有内存分配或对象初始化。通过这种方式,你必须关心在退出时你已经初始化的所有东西,如果你遇到问题,任何函数都会返回false,也要清理它。

在这种情况下,根据我的经验(当我使用CryptoAPI时),最好的方法是创建小类,在构造函数中初始化数据,在析构函数中反初始化数据。下一个函数类必须是前一个函数类的子类。如果出错-抛出异常。

class CondA
{
public:
    CondA() { 
        if (!executeStepA()) 
            throw int(1);
        [Initialize data]
    }
    ~CondA() {        
        [Clean data]
    }
    A* _a;
};

class CondB : public CondA
{
public:
    CondB() { 
        if (!executeStepB()) 
            throw int(2);
        [Initialize data]
    }
    ~CondB() {        
        [Clean data]
    }
    B* _b;
};

class CondC : public CondB
{
public:
    CondC() { 
        if (!executeStepC()) 
            throw int(3);
        [Initialize data]
    }
    ~CondC() {        
        [Clean data]
    }
    C* _c;
};

然后在你的代码中你只需要调用:

shared_ptr<CondC> C(nullptr);
try{
    C = make_shared<CondC>();
}
catch(int& e)
{
    //do something
}
if (C != nullptr)
{
   C->a;//work with
   C->b;//work with
   C->c;//work with
}
executeThisFunctionInAnyCase();

我想这是最好的解决方案,如果每次调用ConditionX初始化一些东西,分配内存等。最好确保所有东西都被清理干净。

如果你的代码像你的例子一样简单,并且你的语言支持短路计算,你可以尝试这样做:

StepA() && StepB() && StepC() && StepD();
DoAlways();

如果您将参数传递给函数并返回其他结果,因此您的代码不能以以前的方式编写,那么许多其他答案将更适合解决这个问题。

只做

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

就是这么简单。


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

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

executeThisFunctionInAnyCase();