什么是在C++中返回错误代码的正确方法

Jee*_*eet 22 c++

我正在使用错误代码来处理我的c ++项目中的错误.问题是如何从一个应该返回一些变量/对象的函数返回错误代码.

考虑一下:

long val = myobject.doSomething();
Run Code Online (Sandbox Code Playgroud)

在这里,myobject是某个类的对象.如果doSomething函数遇到某些错误条件,那么它应该如何通知调用者(不使用异常).

可能的解决方案:

  1. 在类中有一个数据成员(比如err_),可以由调用者检查.但是,在共享同一个对象并调用相同函数的多线程应用程序中,这将是不安全的.
  2. 使用一些全局错误变量,在多线程环境中也是同样的问题.

现在如何通知调用者一些错误情况?

JUS*_*ION 28

例如,创建一个模板,称Maybe它由您的返回值类型进行参数化.每当您返回一个值时,将其包装在此模板中,如下所示:

Maybe<long> result = object.somemethod();
Run Code Online (Sandbox Code Playgroud)

Maybe模板将有一个错误代码(可能是一个静态方法)实例化的方式:

return Maybe<long>::error(code);
Run Code Online (Sandbox Code Playgroud)

但通常会返回值:

Maybe<long> retval;
retval = 15;
return retval;
Run Code Online (Sandbox Code Playgroud)

(当然,您必须覆盖适当的构造函数,赋值运算符等)

在客户端,您调用方法来检查错误.

Maybe<long> result = object.somemethod();
if (result.is_error) 
{ 
    ... handle the error ...
}
else
{
    ... use the result ...
}
Run Code Online (Sandbox Code Playgroud)

同样,您需要定义适当的运算符,以便Maybe<long>在需要的地方使用long.

这听起来像很多工作,但实际上这项工作只需要制作一个好的防弹Maybe模板.您还必须对其进行一些性能调整,以避免令人讨厌的开销.如果要使其更加灵活,可以在返回值类型和错误类型上对其进行参数化.(这只是复杂性的微小增加.)

  • +1 - 这很优雅.您可以通过向`bool`添加一个强制转换运算符来扩展它,这样您就可以编写`if(result)`而不是`if(!result.is_error)`并在结果出错时添加异常来访问结果值.我知道抛弃异常是我们正在避免的事情,但这对它来说确实是一个很好的例子. (7认同)
  • 正如我在本页其他地方所说的那样,例外是针对特殊情况(阅读:意外情况).返回代码适用于您希望错误作为正常程序执行的一部分.您不要将异常用作通用信令机制.[查看此列表中的第一项](http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.12)获取一些指导.异常不是返回码,不应该用作一般的返回码机制.使用它们会以最糟糕的"来自"方式混淆代码**和**会花费很多. (4认同)
  • 我会说当它处于错误状态时访问该值是抛出异常的理想情况,实际上,因为它显示了明显的程序员错误:不检查错误返回。 (2认同)
  • 它被称为`boost :: optional`和`boost :: variant`,这些boost库的运行时成本几乎可以忽略不计,因为你放在那里的值是堆栈分配:模板包装一个标志,指示当前存储的值+ a `union`-like结构(可能是原始内存根据当前对象正确对齐). (2认同)

Chr*_*ith 8

你可能想要像Alexandresu的预期<T>成语.

  • 您能在这里总结一下1.5小时的长谈吗?`Expected&lt;T&gt;` 基本上是一个带有 `T` 或 `std::exception_ptr` 的 `Variant` 吗? (3认同)

Mar*_*som 7

您可以返回一个std::pair包含错误代码(或错误对象)和所需返回对象的对象。感兴趣的对象需要一个默认的构造函数或值,这样即使遇到错误也可以返回一些内容。


ant*_*res 6

您可以将变量作为引用传递并在其中返回错误代码.

  • 更常见的做法是传递变量,通过引用得到结果并返回错误代码. (3认同)
  • 这是一种常见但丑陋的做法.预期的<T>成语是一个更好的习惯. (3认同)

iM7*_*M71 5

我看到有很多不错的解决方案,但如果我遇到这种情况,我会以另一种方式处理它。

auto doSomething()
{        
    // calculations
    return std::make_pair(error_code, value)
}

int main()
{
    auto result = doSomething();
    if (!result.first)
    {
        std::cout << result.second;
    }
    else
    {
        std::cout << "Something went wrong: " << result.second;
    }
}
Run Code Online (Sandbox Code Playgroud)

对我来说,这是一个比传递 bool 作为参考更干净的解决方案。auto从c++14开始支持返回类型推导