C++ 以下哪一种是更好的错误处理方法?

C++ 以下哪一种是更好的错误处理方法?,c++,c++11,error-handling,lambda,goto,C++,C++11,Error Handling,Lambda,Goto,假设一个函数中有多个点可能导致相同的失败。以下哪种方法更好?还有更好的选择吗 { ... 如果(某些故障条件0)发生故障; ... 如果(某些故障条件1)发生故障; ... 如果(某些故障条件2)发生故障; ... 如果(…){ ... } 否则如果(…){ ... } 否则就会失败; ... 返回; 失败: /*在这里处理错误*/ ... } 或 { 自动失败=[]{ /*在这里处理错误*/ ... }; ... 如果(某些条件0)失败(); ... 如果(某些失败条件1)失败(); ..

假设一个函数中有多个点可能导致相同的失败。以下哪种方法更好?还有更好的选择吗

{
...
如果(某些故障条件0)发生故障;
...
如果(某些故障条件1)发生故障;
...
如果(某些故障条件2)发生故障;
...
如果(…){
...
}
否则如果(…){
...
}
否则就会失败;
...
返回;
失败:
/*在这里处理错误*/
...
}

{
自动失败=[]{
/*在这里处理错误*/
... 
};
...
如果(某些条件0)失败();
...
如果(某些失败条件1)失败();
...
如果(某些失败条件2)失败();
...
如果(…){
...
}
否则如果(…){
...
}
否则失败();
...
}
这个怎么样

#define MY_FAIL_CHECK(_condition) if(_condition) { throw some_exception; }

void foo()
{
  MY_FAIL_CHECK(some_failure_condition0);
  MY_FAIL_CHECK(some_failure_condition1);
  MY_FAIL_CHECK(some_failure_condition2);
}

因为这是C++而不是C,更好的选择是使用异常来保证析构函数被适当调用:

try
{
    ...
    if (some_failure_condition0) throw fail;
    ...
    if (some_failure_condition1) throw fail;
    ...
    if (some_failure_condition2) throw fail;
    ...
    if (...) {
        ...
    }
    else if (...) {
        ...
    }
    else throw fail;
    ...
    return;
}
catch(const fail& f)
    /* handle error here */
    ...
}

如果你使用C++,没有理由使用GOTO来代替异常。

一般来说,这完全取决于函数的语义是什么。我通常会避免goto(我已经多年没有使用它了),也会避免使用返回代码进行C风格的错误处理。对于错误处理,我坚持以下准则:

  • 将RAII用于资源以获得自动异常安全处理,例如,不显式调用new
  • 当函数无法建立其后置条件(如果是成员函数,则类不变量)时,抛出异常。例如,如果您想从中接收数据的网络连接未打开,但由于没有可用数据,通过网络接收数据失败,则不会抛出该连接
  • 如果“错误”是函数的预期结果,例如,通过网络接收数据,但没有人发送数据,我将使用可以处理该问题的返回类型。在本例中,它可能是一个空向量,但一般来说,类似boost::optional这样的东西是有意义的
  • 完成函数时需要执行的代码应该在范围内。这通常是一个临时的RAII对象,所以我经常创建一个新的RAII来重用它

  • 这使得像您的示例这样的代码在我生命中的大部分时间都过时了。

    我将创建子函数,类似于:

    bool foo() // or enum or boost::optional
    {
        ...
        if (some_failure_condition0) return false;
        ...
        if (some_failure_condition1) return false;
        ...
        if (some_failure_condition2) return false;
        ...
        if (...) {
            ...
        }
        else if (...) {
            ...
        }
        else return false;
        ...
        return true;
    }
    
    void bar()
    {
        auto result = foo();
        if (!result)
        {
            /* handle error here */
            ...
        }
    }
    

    不要忘记使用RAII来避免一些可能是自动的处理。

    如果(某些故障条件X)抛出一些异常,为什么不
    ?@praetorian以避免不必要的代码重复。使用异常控制流是使用异常的错误方式!!如果代码是dup,只需编写一个自由函数。您正在重复相同的短表达式。在这种情况下,我不会太担心重复。另一个选项可能是
    auto throw_if_fail=[](bool failed){if(failed)throw some_exception;};如果失败则抛出(某些失败条件X)goto),正如语言标准中所规定的那样,goto更容易阅读。然而,你必须熟悉cusom宏。@Sheridan此外,当我打算让我的示例更一般时,你将我的示例解释为非常具体。我已经更新了,明白了。我会使用宏或lambda。但错误处理的更好方法是使用C++的异常,如果感觉清晰、简单、直接,没有理由避免GOTO。如果程序流不是真正的异常,那么使用异常而不是goto也是不好的做法!