假设我正在使用一个带有函数to_int
的库,它接受一个字符串参数。如果字符串是数字的字符表示,则此函数返回int,例如"23"
将返回23
。如果字符串不是数字,则抛出std::runtime_error
。会不会更好:
if(is_all_digits(str))
x = to_int(str);
else
output("not an int, idiot. Try again");
或者
try
{
x = to_int(str);
}
catch(...)
{
output("not an int, idiot. Try again");
}
答案 0 :(得分:2)
有几种不同的错误处理技术,每种技术都有优点和缺点。
让我们考虑一个函数getAllElements()
,它获取一个带有一些元素的容器。
现在这可能会产生错误(数据库连接或其他)。您现在有了选项
Errorcode getAllElements(std::vector<...> & cont);
或
std::vector<...> getAllElements(); //throws exceptions
这通常是一种一般性的设计问题,取决于具体情况。出于多种原因,我更喜欢具有例外的那个。我可以分配并且不需要预定的容器
auto elements = getAllElements();
接下来是你会在哪里处理你的错误?如果您像堆栈中的5个函数一样处理它们,则必须每次检查错误代码并将其提供给下一个函数。一个例外会自动传播,直到有人抓住它并能够处理它。
例外虽然有一些缺点。它们会导致更大的二进制文件,并在抛出异常时更慢。在游戏开发中通常没有使用例外(听听这个以获取更多信息:http://cppcast.com/2016/10/guy-davidson/他们谈论为什么不使用例外。我现在没有时间戳。)
在特殊情况下也应使用例外情况。你不能立即处理的错误,必须在更高的地方处理。
因此,如果您不需要高性能/小二进制文件,我建议您使用有用的异常。它们可以导致输入更少的代码(例如检查返回代码),这可以减少引入错误的位置。
以下是CppCon 2016错误处理机制的一个很好的讨论: CppCon 2016: Patrice Roy “The Exception Situation"
答案 1 :(得分:1)
这个问题没有一个答案,因为它取决于整个程序如何处理错误输入,以及检测到错误时是否可以明智地恢复(无论是使用返回代码报告这些错误还是抛出异常)。
每个调用to_int()
的函数都可以立即从错误的输入中恢复吗?如果没有,最好允许抛出异常....所以它会解除堆栈,直到有一些调用者(带有try/catch
块)可以实际从错误中恢复。
如果您有许多调用to_int()
的函数,您想要对每个函数进行检查,该怎么办?如果是这样,这会导致大量代码重复。
如果你有一些调用to_int()
的函数可以立即从错误中恢复而其他一些函数不可以恢复怎么办?
如果您想向调用者报告错误(例如,允许比编写错误字符串更重要的内容),该怎么办?
什么没有is_all_digits()
功能?如果没有,如果您以错过to_int()
将检测到的某些错误的方式实现它会怎样?然后你有两个世界中最糟糕的 - 进行错误检查以试图阻止抛出异常,但随后函数抛出异常。例如,可能存在一些全局设置导致to_int()
仅接受八进制数字(范围0
到7
),但您的is_all_digits()
函数认为所有十进制数字都是是有效的。
更一般地说,真正需要的是定义一个适用于整个程序的错误处理策略。试图根据单个函数的用法决定抛出异常或不抛出异常,这完全忽略了这一点。
如果您的程序使用异常报告错误是有意义的(例如,在try/catch
中使用单个集中main()
块,那么所有错误都会在调用堆栈中传播,因此main()
实现了恢复全局)然后抛出异常。如果程序中的每个函数都能检测到错误并在现场默默处理它们,那么请避免异常。
我所倡导的是允许狗(你的程序)摇尾巴(关于如何处理错误的低级决策)。你的问题基本上是要让尾巴摇尾巴是否合适。
答案 2 :(得分:0)
如果捕获的异常确实特定于你可以使用特定的try catch(使用通用的try catch不是一个好主意,因为你隐藏了一堆其他可能的错误)
一般来说,我的首选是在将字符串传递给函数之前检查字符串。
答案 3 :(得分:0)
当您使用库或API时,您希望它可以防止您使用不良和其他错误。
这是你的函数控制给定参数的完整性和抛出异常的角色。
请注意,您还可以在开发代码时使用断言,然后禁用它以进行二进制生成。