代码之家  ›  专栏  ›  技术社区  ›  nakiya

如何更改错误处理方法

  •  0
  • nakiya  · 技术社区  · 15 年前

    我似乎无法理解为什么人们说C++异常更好。例如,我有一个应用程序,它从要在应用程序中使用的共享对象加载函数对象。事情是这样的:

    bool LoadFunctions()
    {
       //Get Function factory.
       FunctionFactory& oFactory = GetFunctionFactory();
       //Create functions from the factory and use.
    }
    
    FunctionFactory& GetFunctionFactory()
    {
       //Get shared object handle.
       void* pHandle = dlopen("someso.so");
    
       //Get function ptr for Factory getter.
       typedef FunctionFactory* (*tpfFacGet)();
       tpfFacGet pF = static_cast<tpfFacGet>(dlsym(pHandle, "GetFactory"));
    
       //Call function and return object.
       return *((*pF)());
    }
    

    现在,很容易看出很多东西都可能出错。如果我像往常那样做,我会返回指针而不是引用,并检查它们是否 NULL 打印一条错误消息,如果没有,就退出。这样,我知道哪里出了问题,甚至可以尝试从中恢复(也就是说,如果我成功地加载了工厂,但只加载了一个函数失败,我可能还会继续)。我不明白的是如何在这种情况下使用异常,以及如何恢复程序,而不是打印错误消息和qut。有人能告诉我如何用C++的方式做这件事吗?

    3 回复  |  直到 15 年前
        1
  •  2
  •   Moo-Juice    15 年前

    我们甚至不需要返回码。如果出现问题,它应该在异常中。

    int main()
    {
        try
        {
            LoadFunctions();
            // if we're here, everything succeeded!
        }
        catch(std::exception _e)
        {
            // output exception message, quit gracefully
        } 
    
        // IRRESPECTIVE OF SUCCESS/FAILURE WE END UP HERE
    
        return 0;
    } // eo main
    

    编辑:

    好吧,假设你有一个加载函数的替代方法 LoadFunctions() 失败。你可能会在 catch 处理程序,但这样您将很快得到大量嵌套的异常处理程序,这只会使事情复杂化。

    所以现在我们开始讨论 设计 . LoadFunctions 如果函数已加载,则应成功;如果函数未加载,则应抛出异常。在这个加载函数的替代方法的假设示例中,该调用应该在 加载函数 方法。此替代方法不需要对调用方可见。

    在最高层,我们要么以功能结束,要么不以功能结束。编写良好的异常处理, 在我看来 是为了摆脱灰色地带。函数执行了命令的操作,或者没有执行。

        2
  •  0
  •   CashCow    15 年前

    正如你所说,有很多可能会出错。顺便说一句,你不会在那儿碰到坏演员的。如果符号存在,但不是你投给它的类型,稍后你会受到严重的冲击。

    如果你要避免异常,你需要找个地方报告错误。因为LoadFunctions和GetFunctionFactory()不知道如何处理错误(记录它?打印到stderr?设置一个消息框?)它唯一能做的就是生成错误。

    在C语言中,一种常见的方法是传入一个参数,如果出现错误,它可以将错误放入该参数中,并让每个函数在继续之前“检查”成功。这会使流程变得相当复杂。

    “抛出”异常的C++概念意味着不需要通过每个函数传递指针(或引用)。在错误发生的地方,你生成错误并“抛出”它——有点像“喊”它。这将导致所有代码(除析构函数中的清理外)停止,直到找到一个按所需方式处理错误的捕获器。

    请注意,异常通常只应用于处理错误,而不是通常发生的情况,例如在您知道读取已完成的情况下遇到“文件结尾”。

        3
  •  0
  •   itaj    15 年前

    使用异常而不是返回值(或任何其他方法)不应该改变代码的行为,只应该改变代码的编写和组织方式。这基本上意味着,首先要确定某个错误的恢复是什么,是更优雅还是更少,然后编写代码来执行该操作。 大多数有经验的程序员(实际上都是)都认为异常是比返回值好得多的方法。在几个函数的简短示例中看不到很大的区别,但在包含数千个函数和类型的实际系统中,您会清楚地看到它。我不想再详细说明它是如何变得更好的。 不管怎样,我建议你应该习惯默认使用异常。但是请注意,使用异常有一些微妙的问题(例如RAII http://en.wikipedia.org/wiki/RAII ),这最终会使您的代码更好,但是您应该在一本书中阅读它们(我将无法在这里描述并感觉到我对主题做了公正的描述)。 我认为这本书的“有效C++ + Scott Meyer”处理,当然“例外C++/Habor萨特”。如果你还没有读过这些书,这些书对任何c++开发人员来说都是一个很好的开始。