Adr*_*thy 11
错误通常在代码中检测到非常低的级别,但处理的级别非常高.如果对这些使用返回代码,则必须设计所有中间级别以期望低级代码并将其传播直到处理它.除了例外,你只需要抛出低水平,并抓住高水平(如果有的话).只要您的中级代码使用RAII,您就不必更改其中任何一个来执行错误传播.
所以我经常考虑错误的类型以及错误的处理方式.如果调用者可能会处理问题,因为它预计会是常见的事情,那么返回代码就很棒了.如果错误是灾难性的(无法分配必要的资源),那么不能指望直接调用者处理它.
其他需要考虑的事项:异常不能忽略,返回代码可以.如果问题无法处理会很危险,请使用例外.
从技术上讲,异常不能通过C代码传播回来.(它适用于许多系统,但它不可移植也不保证.)因此,如果你有一个C库回调你的C++代码,你可能不应该从回调中抛出异常.同样对于线程边界等
其中一些可能会重复内容,但这里有关于使用其中一个的简单提示:
您的函数可能无法使用标记值来发出错误信号,因为该函数使用所有可能的值作为有效答案。这可能发生在不同的情况下,最显着的是整数数值算法。0and-1通常用作特殊值,但一些相当常见的算法,包括pow可能无法使用这些(即0^1=0和-1^3=-1)。因此,选择合适的值有点像一门艺术,一致性是一个问题,用户必须记住每个特殊情况的错误值。
一些 API 认识到这一点,并且(几乎)从不使用真正的返回值,但始终依赖按引用返回的语义,并将所有函数中的返回值用作状态代码,要么是某个(标准)“成功”值,要么是一个特定于功能的错误代码。例如,CUDA 就有这样的约定。
错误代码通常被称为“更有效”(其他答案之一中的评论解释了为什么这不一定是真的)。但是,它们有两个常见问题。
The operation failed.消息而不是Ran out of disk space.。为了解决 (1),默认情况下会传播异常。故意忽略错误在代码中变得显而易见,而不是隐藏。为了解决 (2),异常使用类型系统,阻止您编译具有冲突错误“值”的程序。此外,使用异常类层次结构,您可以表示相关结果的“系列”。(注意:这经常被误用,人们捕捉Exception而不是NoMoreDiskSpace并仍然显示通用The operation failed.消息)。
有些人会在他们的应用程序中推荐两者的混合,但恕我直言,这会导致两种系统都被误用的情况。在这些混合约定中,由于混淆,通常不会捕获异常,也不会检查错误代码。一方面,由于异常仅用于异常情况,因此假定它们永远不会发生,或者根本无法处理。另一方面,返回错误代码的失败被认为是轻微的,根本没有被处理。当然,由每个程序员来决定某种情况是否异常,导致在检查什么错误代码和捕获什么异常之间产生很多混淆。
无论您选择哪种系统,请务必充分利用它,并对其使用保持一致。
| 归档时间: |
|
| 查看次数: |
5225 次 |
| 最近记录: |