【问题标题】:Making the code cleaner [closed]使代码更干净[关闭]
【发布时间】:2013-12-27 22:44:27
【问题描述】:

对不起,如果这个问题不适合 SO。

我有一个类似于下面给出的 MyFun() 的 C++ 函数。

从这个函数中,我调用了一些(比如大约 30 个)返回布尔变量的其他函数(true 表示成功,false 表示失败)。如果这些函数中的任何一个返回 false,我也必须从 MyFun() 返回 false。另外,如果中间函数调用失败,我不应该立即退出(不调用其余函数)。

目前我正在这样做,如下所示,但感觉可能有一种更简洁/更简洁的方式来处理这个问题。任何建议表示赞赏。

非常感谢。

bool MyFun() // fn that returns false on failure
{
    bool Result = true;

    if (false == AnotherFn1()) // Another fn that returns false on failure
    {
        Result = false;
    }

    if (false == AnotherFn2()) // Another fn that returns false on failure
    {
        Result = false;
    }

     // Repeat this a number of times.
    .
    .
    .


    if (false == Result)
    {
         cout << "Some function call failed";
    }

    return Result;
}

【问题讨论】:

  • Sorry if this question is suited for SO 上帝我知道我讨厌这种情况发生
  • @LightnessRacesinOrbit : 错字........ :)
  • 这个问题似乎是题外话,因为它属于codereview.stackexchange.com
  • @stefan:你真的建议过这个吗?抱歉,我对 SO 不太熟悉。
  • @NeonGlow:公平地说,这是真的。

标签: c++


【解决方案1】:

我会用更简洁的按位与赋值替换每个if 语句:

bool MyFun() // fn that returns false on failure
{
    bool Result = true;

    Result &= AnotherFn1(); // Another fn that returns false on failure

    Result &= AnotherFn2(); // Another fn that returns false on failure

     // Repeat this a number of times.
    .
    .
    .
    if (false == Result)
    {
       cout << "Some function call failed";
    }

    return Result;
}

【讨论】:

  • 我一直在寻找这样的东西。这将有助于减少代码行数。谢谢。
  • @HAL9000 - 更好地使用 &&= 而不是 &=。请更新答案
  • @egur:我完全同意你的看法!我将编辑我的答案,谢谢。
  • @egur:看这里stackoverflow.com/questions/2488406/… 我改变了主意,我留下了我原来的答案。
  • 我认为这个答案是完美的,并且使用按位 & 更有意义,特别是如果 OP 更喜欢将所有 &= 语句合并为 Result &amp;= AnotherFn1() &amp; AnotherFn2() &amp; AnotherFn3();
【解决方案2】:

使用类似于std::vector 或std::function 的东西。它更易于维护。

示例:http://ideone.com/0voxRl

// List all the function you want to evaluate
std::vector<std::function<bool()>> functions = {
    my_func1,
    my_func2,
    my_func3,
    my_func4
  };

// Evaluate all the function returning the number of function that did fail.
unsigned long failure =
    std::count_if(functions.begin(), functions.end(),
        [](const std::function<bool()>& function) { return !function(); });

如果你想在函数失败时停止,你只需要使用std::all_of 而不是std::count_if。您将控制流与函数列表分离,在我看来,这是一件好事。

您可以通过使用名称作为键的函数映射来改进这一点,这将允许您输出哪个函数失败:

std::map<std::string, std::function<bool()>> function_map;

【讨论】:

  • 非常好的方法。我不知道这是可能的。所以我可以放弃我丑陋的功能。指针。
  • 这是我会推荐的。我希望这被选为正确答案。如果 C++ 存在带有 foldLeft 的解决方案,那将会很有趣。不知道累积能不能用。
  • @RobertBiter 可以使用std::accumulate(functions.begin(), functions.end(), [](const std::function&lt;bool()&gt;&amp; function, bool value) { return function() &amp;&amp; value; }, true); 之类的东西,但它不会使代码更清晰。
【解决方案3】:
bool MyFun() // fn that returns false on failure
{
    bool Result = true;

    // if need to call every function, despite of the Result of the previous
    Result = AnotherFn1() && Result;
    Result = AnotherFn2() && Result;

    // if need to avoid calling any other function after some failure
    Result = Result && AnotherFn1();
    Result = Result && AnotherFn2();

    return Result;
}

【讨论】:

    【解决方案4】:

    代替

    if (false == AnotherFn1()) // Another fn that returns false on failure
    {
        Result = false;
    }
    
    if (false == AnotherFn2()) // Another fn that returns false on failure
    {
        Result = false;
    }
    
    if (false == AnotherFn3()) // Another fn that returns false on failure
    {
        Result = false;
    }
    

    开始使用布尔值,真值:

    if (!AnotherFn1()) // Another fn that returns false on failure
    {
        Result = false;
    }
    
    if (!AnotherFn2()) // Another fn that returns false on failure
    {
        Result = false;
    }
    
    if (!AnotherFn3()) // Another fn that returns false on failure
    {
        Result = false;
    }
    

    那么,所有这些条件都有相同的代码;它们基本上是一个大条件的一部分:

    if ( !AnotherFn1()
       | !AnotherFn2()
       | !AnotherFn3())
    {
        Result = false;
    }
    

    对于您希望调用所有函数的特定问题,即使您很早就知道会返回false,但重要的是不要使用短路运算符&amp;&amp; 和||。使用急切的按位运算符 | 和 &amp; 确实是一个 hack,因为它们是按位而不是布尔值(因此隐藏了意图),但在你的情况下工作,如果 AnotherFn? return strict bools。

    你可以否定你在里面所做的;更少的否定产生更好的代码:

    Result = false;
    
    
    if ( AnotherFn1()
       & AnotherFn2()
       & AnotherFn3())
    {
        Result = true;
    }
    

    然后你可以摆脱这些分配,直接返回:

    if ( AnotherFn1()
       & AnotherFn2()
       & AnotherFn3())
    {
        return true;
    }
    
    cout << "something bad happened";
    return false;
    

    总结

    旧:

    bool MyFun() // fn that returns false on failure
    {
        bool Result = true;
    
        if (false == AnotherFn1()) // Another fn that returns false on failure
        {
            Result = false;
        }
    
        if (false == AnotherFn2()) // Another fn that returns false on failure
        {
            Result = false;
        }
    
         // Repeat this a number of times.
        .
        .
        .
    
    
        if (false == Result)
        {
             cout << "Some function call failed";
        }
    
        return Result;
    }
    

    新:

    bool MyFun() // fn that returns false on failure
    {
        if (AnotherFn1() &
            AnotherFn2() &
            AnotherFn3())
        {
            return true;
        }
        cout << "Some function call failed";
        return false;
    }
    

    还有更多可能的改进,例如使用异常而不是错误代码,但不要试图处理“期望”。

    【讨论】:

    • 这不是相同的行为。在旧版本中,始终评估所有功能,而不是在您的版本中。
    • @phresnel 我认为你是对的
    • @Johan:我错过了这是一项要求。我改变了答案。
    【解决方案5】:

    ! 可以用作 false

    的更简洁的替代品

    像这样:

    bool MyFun() // fn that returns false on failure
    {
    bool Result = true;
    
    if (!AnotherFn1()) // Another fn that returns false on failure
    {
        Result = false;
    }
    
    if (!AnotherFn2()) // Another fn that returns false on failure
    {
        Result = false;
    }
    
     // Repeat this a number of times.
    .
    .
    .
    
    
    if (!Result)
    {
         cout << "Some function call failed";
    }
    
    return Result;
    

    }

    【讨论】:

      【解决方案6】:

      如何使用异常处理失败:a neat exemple

      主要问题是,函数调用是否相互依赖?如果前一个失败,可以跳过一些吗? ...

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-03-11
        • 2016-09-15
        • 1970-01-01
        • 2021-07-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多