当前位置:  开发笔记 > 编程语言 > 正文

在C++中,使用异常和try/catch而不仅仅返回错误代码有什么好处?

如何解决《在C++中,使用异常和try/catch而不仅仅返回错误代码有什么好处?》经验,为你挑选了7个好方法。

我已经编写了很长时间的C和C++,到目前为止我从未使用过异常和try/catch.使用它有什么好处,而不仅仅是让函数返回错误代码?



1> Martin..:

可能是一个明显的观点 - 开发人员可以忽略(或不知道)您的返回状态,并继续幸福地意识到某些事情失败了.

需要以某种方式承认异常 - 如果没有积极地放置某些东西,就不能无声地忽略它.


您有以下两点之一:您可以轻松地将处理错误的代码移动到非本地点(更高的调用更改),知道如何在给定更广泛的上下文的情况下处理问题.

2> James Curran..:

例外的优点有两个:

他们不容忽视. 您必须在某个级别处理它们,否则它们将终止您的程序.使用错误代码,您必须明确检查它们,否则它们将丢失.

他们可以被忽略. 如果错误无法在一个级别处理,它将自动冒泡到下一个级别,它可以在哪个级别.必须明确传递错误代码,直到它们达到可以处理的级别.



3> Eclipse..:

优点是您不必在每次可能失败的呼叫后检查错误代码.为了实现这一点,您需要将它与RAII类结合使用,以便在堆栈展开时自动清理所有内容.

有错误消息:

int DoSomeThings()
{
    int error = 0;
    HandleA hA;
    error = CreateAObject(&ha);
    if (error)
       goto cleanUpFailedA;

    HandleB hB;
    error = CreateBObjectWithA(hA, &hB);
    if (error)
       goto cleanUpFailedB;

    HandleC hC;
    error = CreateCObjectWithA(hB, &hC);
    if (error)
       goto cleanUpFailedC;

    ...

    cleanUpFailedC:
       DeleteCObject(hC);
    cleanUpFailedB:
       DeleteBObject(hB);
    cleanUpFailedA:
       DeleteAObject(hA);

    return error;
}

有例外和RAII

void DoSomeThings()
{
    RAIIHandleA hA = CreateAObject();
    RAIIHandleB hB = CreateBObjectWithA(hA);
    RAIIHandleC hC = CreateCObjectWithB(hB);
    ...
}

struct RAIIHandleA
{
    HandleA Handle;
    RAIIHandleA(HandleA handle) : Handle(handle) {}
    ~RAIIHandleA() { DeleteAObject(Handle); }
}
...

乍一看,RAII/Exceptions版本似乎更长,直到您意识到清理代码只需要编写一次(并且有方法可以简化).但DoSomeThings的第二个版本更清晰,更易于维护.

不要在没有RAII习语的情况下尝试在C++中使用异常,因为您会泄漏资源和内存.所有清理工作都需要在堆栈分配对象的析构函数中完成.

我意识到还有其他方法可以进行错误代码处理,但它们最终看起来有点相同.如果你删除了gotos,你最终会重复清理代码.

错误代码的一点是,它们可以明显地显示事情可能失败的地方,以及它们如何失败.在上面的代码中,您假设事情不会失败(但如果它们确实存在,您将受到RAII包装器的保护).但是你最不应该注意事情可能出错的地方.



4> Bill the Liz..:

异常处理很有用,因为它可以很容易地将错误处理代码与为处理程序功能而编写的代码分开.这使得读取和编写代码更容易.



5> Gerald..:

除了提到的其他内容之外,您无法从构造函数返回错误代码.析构函数,但你应该避免从析构函数中抛出异常.



6> Steven A. Lo..:

返回错误代码时发生错误情况,预计在某些情况下,

在任何情况下都不期望错误条件时抛出异常

在前一种情况下,函数的调用者必须检查错误代码的预期失败; 在后一种情况下,异常可以由适当的堆栈(或默认处理程序)上的任何调用者处理



7> Anthony Will..:

我写了一篇有关此问题的博客文章(Elegant Code的例外情况),该文章随后在Overload中发布。我实际上是为了回应Joel在StackOverflow播客上说的话而写的!

无论如何,我坚信在大多数情况下,异常优于错误代码。我发现使用返回错误代码的函数真的很痛苦:您必须在每次调用后检查错误代码,这可能会中断调用代码的流程。这也意味着您不能使用重载运算符,因为没有任何方法可以指示错误。

检查错误代码的痛苦意味着人们经常会忽略这样做,从而使它们完全毫无意义:至少您必须使用catch语句明确地忽略异常。

在C ++中使用析构函数以及在.NET中使用释放程序来确保在出现异常的情况下正确释放资源也可以大大简化代码。为了获得与错误代码相同的保护级别,您要么需要大量的if语句,需要大量重复的清除代码,要么goto在函数结尾处调用公共清除块。这些选择都不是令人愉快的。

推荐阅读
mylvfamily
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有