可以使用C++;例外情况是合理的 我有一个C++ API,它在异常条件下抛出异常。通常,我在C++ API中看到的错误通知方法是通过特殊的返回代码和函数返回最后一个错误字符串,如果方法返回错误代码,则可以检查这些错误字符串。此方法有一些限制,例如,如果需要从函数返回一个整数,并且整个整数值范围对于返回值有效,因此不能返回错误代码

可以使用C++;例外情况是合理的 我有一个C++ API,它在异常条件下抛出异常。通常,我在C++ API中看到的错误通知方法是通过特殊的返回代码和函数返回最后一个错误字符串,如果方法返回错误代码,则可以检查这些错误字符串。此方法有一些限制,例如,如果需要从函数返回一个整数,并且整个整数值范围对于返回值有效,因此不能返回错误代码,c++,exception,exception-handling,C++,Exception,Exception Handling,因此,当函数中发生错误时,我选择在API中抛出异常 这是C++中异常的可接受用法吗? 此外,在API中的某些函数(例如authenticate())中,我有两个选项 返回bool表示成功 返回void并在失败时引发异常 如果使用第一个选项,它与其他函数不一致,因为它们都抛出异常。此外,很难指出错误是什么 那么在这样的函数中也可以使用第二种方法吗 在下面的回答中,提到使用C++异常来控制程序流是不好的。此外,我在其他地方也听到过同样的情况 我的用法是否违反了这一点?我无法清楚地确定我是否在这里使

因此,当函数中发生错误时,我选择在API中抛出异常

这是C++中异常的可接受用法吗? 此外,在API中的某些函数(例如authenticate())中,我有两个选项

  • 返回bool表示成功
  • 返回void并在失败时引发异常
  • 如果使用第一个选项,它与其他函数不一致,因为它们都抛出异常。此外,很难指出错误是什么

    那么在这样的函数中也可以使用第二种方法吗

    在下面的回答中,提到使用C++异常来控制程序流是不好的。此外,我在其他地方也听到过同样的情况


    我的用法是否违反了这一点?我无法清楚地确定我是否在这里使用异常来控制程序流。

    对于类似于
    authenticate()
    的内容,如果您能够计算身份验证的真/假值,我希望您返回bool,如果有什么阻止您这样做,则抛出异常。关于在流控制中使用异常的评论建议不要执行以下操作:

    try {
       ...
       authenticate();
       // rely on the exception to not execute the rest of the code.
       ...
    } catch (...) { ... }
    
    例如,我可以想象一个依赖于联系某个服务的
    authenticate()
    方法,如果由于某种原因无法与该服务通信,则不知道凭据是好是坏


    同样,API的另一个主要经验法则是“保持一致”。如果API的其余部分依赖异常作为类似情况下的假值,请使用它,但对我来说,这有点不好。我倾向于为例外情况保留例外情况,即罕见的,在正常操作中不应该发生的情况。

    对于类似
    authenticate()
    ,如果能够计算验证的真/假值,我希望您返回bool,如果有什么事情阻止你这么做,抛出一个异常。关于在流控制中使用异常的评论建议不要执行以下操作:

    try {
       ...
       authenticate();
       // rely on the exception to not execute the rest of the code.
       ...
    } catch (...) { ... }
    
    例如,我可以想象一个依赖于联系某个服务的
    authenticate()
    方法,如果由于某种原因无法与该服务通信,则不知道凭据是好是坏

    同样,API的另一个主要经验法则是“保持一致”。如果API的其余部分依赖异常作为类似情况下的假值,请使用它,但对我来说,这有点不好。我倾向于为例外情况保留例外情况,即罕见的,在正常操作中不应该发生的情况

    < >我在C++ API中看到的错误通知方法是用特殊的返回代码和函数返回最后一个错误字符串,如果方法返回错误代码,可以检查。 <>有时候这是出于好的原因,但是当你看到C++库包装一个较老的C库时,更多的是由一个更舒服的C编写的,为客户代码编写的C更舒服,或者是与C<P/P写的互操作性。 从函数返回一个整数,整个整数值范围对返回值有效,因此不能返回错误代码

    选择包括:

    • 例外情况

    • 以更宽的类型返回(例如返回
      int
      ,其中
      -1
      表示EOF)

    • 在值旁边返回一个成功标志,包装为
      boost::optional
      pair
      tuple
      struct

    • 调用方至少拥有一个成功标志和/或值,并通过引用或指针参数将其指定为函数的非const

    这是C++中异常的可接受用法吗? 听起来不错,但艺术在于平衡利弊,我们不知道客户端代码调用函数是否最方便、最健壮。理解他们的期望在关键,这将部分地基于他们的整体C++经验,而且还从你的API和其他任何API,同时你的运输,甚至从其他API,他们可能会在相同的应用程序使用其他的图书馆等。 还要考虑函数的调用方是否可能希望在调用上下文中处理该函数的成功或失败,而不是其他可能的失败。例如,有时客户端代码更容易处理返回布尔成功值的函数:

    if (fn(1) && !fn(2))
        fn(3);
    
    try
    {
        fn(1);
        try
        {
            fn2();
        }
        catch (const ExpectedExceptionFromFn2Type&)
        {
            fn3();
        }
    }
    catch (const PossibleExceptionFromFn1Type&)
    {
        // that's ok - we don't care...
    }
    
    但在其他情况下,除以下例外情况外,这可能更容易:

    try
    {
        My_X x { get_X(99) };
        if (x.is_happy(42))
            x += next_prime_after(x.to_int() * 3);
    }
    catch (std::exception& e)
    {
        std::cerr << "oops\n";
    }
    
    ……或者

    enum Errors_By { Return_Value, Exception };
    bool authenticate(Errors_By e) { ... if (e == Exception) throw ...; return ...; }
    
    template <class Error_Policy>
    struct System
    {
         bool authenticate() { ... Error_Policy::return_or_throw(...); }
         ...
    }
    
    ……或者

    enum Errors_By { Return_Value, Exception };
    bool authenticate(Errors_By e) { ... if (e == Exception) throw ...; return ...; }
    
    template <class Error_Policy>
    struct System
    {
         bool authenticate() { ... Error_Policy::return_or_throw(...); }
         ...
    }
    
    模板
    结构系统
    {
    bool authenticate(){…错误策略::返回或抛出(…);}
    ...
    }
    
    另外,在API中的一些函数中(例如,
    authenticate()
    ),我有两个选项

    如上所述,您有两个以上的选项。无论如何,一致性是非常重要的。听起来例外是合适的

    提到使用C++异常来控制程序流程

    是不好的。 这正是异常所做的,以及它们可以用来做的一切,但我确实理解你的意思。最终,考虑到您的客户将与您的客户一起使用的其他库等,在使用大量其他软件的同时达到正确的平衡是一门艺术。。也就是说,如果某事物在某种意义上是一个“错误”,那么它至少是合理的。