什么时候应该抛出异常?
我正在制作一个C++游戏gui lib,并想知道我什么时候应该抛出异常。例如,现在,如果我得到一个NULL指针,该函数就会失败。我应该抛出一个异常吗?它不是真的会导致它崩溃。什么是引发异常的好地方的例子?什么时候应该抛出异常?
感谢
这个问题的通常答案是,你应该只在'特殊'情况下抛出异常。但是什么是特殊情况。一些例子:
- 你的控制范围之外的活动(如内存溢出,丢失的文件)
- 非法参数传递给你的方法(即你指定你的方法需要一个手柄和调用者传递NULL)
将异常作为应用程序正常流程的一部分抛出通常是一个糟糕的主意,但是又要由您来定义应用程序的正常流程。但看待它的一种方式是,您的API应该指定它将接受的有效输入的范围 - 并且您不应该针对这些输入引发异常。
此主题在本网站和其他地方已经涵盖了很多,所以使用您的标题的谷歌搜索将引发更多的例子和评论。
关于你的具体应用 - 可能会得到一些其他游戏gui库的api来感受这些库的工作方式(假设你认为它们设计得很好)。
它完全取决于你想在未来使用你的代码,你在做什么和什么。
当某件事情失败并且您没有任何选择时,您应该抛出异常,或者从技术上说,尝试修复这种情况并不是最佳选择;换句话说,从你的角度来看是一个问题。
沉默失败是一个最糟糕的想法,如果你在谈论图书馆写作,我会听到这个想法。
非常普遍:当出现异常情况时抛出异常。在你的例子中,如果null
是可接受的定义行为的输入,那么不要抛出异常。如果null
是非法的输入,那么你应该抛出一个异常来告诉调用者有什么问题。
你必须报告某种失败。你可以用异常或状态代码来做到这一点。就我个人而言,如果可能的话,我倾向于状态代码,特别是在库代码中。
曾经有一段时间,你不能确定一个异常实际上会被捕获,除非执行捕获的代码是由相同编译器的版本和引发异常的代码相同的标记构建的。这似乎很大程度上解决了标准ABI实际上具有事实上的平台。但是,一旦我习惯于无例外地报告库代码中的故障,我发现有充足的理由继续这样做。
其中之一,图书馆是为第三方使用,并且这些党可能不会对writing exception safe code太兴奋。
异常安全代码不仅仅是资源管理。试想一下:
...
// m is a mutex
boost::scoped_lock(m); // now I can't forget to release the mutex
withdraw_money(acct1, 1000);
function_that_may_throw_exception();
deposit_money(acct2, 1000);
当然有可能改写这个:
// using Boost SCOPE_EXIT
bool commit = false;
boost::scoped_lock(m);
withdraw_money(acct1, 1000);
SCOPE_EXIT((&commit) (&acct1))
{
if (!commit) {
deposit_money(acct1, 1000);
}
}
function_that_may_throw_exception();
deposit_money(acct2, 1000);
commit = true;
例外解决很多问题,但他们没有解决的错误处理/检测相关的所有问题。编写无效的代码尽管有例外情况,但与状态代码一样。
任何事情都比默默地失败更好。 – 2010-11-02 00:15:52
如果您正在编写图书馆,您可能需要将来再使用它,或将其分发给朋友/同事。就我个人而言,我会在所有地方抛出异常,给我处理它的灵活性或在最终应用程序中忽略它,而不是在图书馆默默地失败。 – dotalchemy 2010-11-02 00:19:07
更好的是你为什么使用指针而不是引用,特别是如果你必须引用一个有效的对象。 – GManNickG 2010-11-02 00:29:05