C++ 中的通用异常处理

Posted

技术标签:

【中文标题】C++ 中的通用异常处理【英文标题】:Generic exception handling in C++ 【发布时间】:2017-01-25 01:06:13 【问题描述】:

在python中你可以使用:

try:
    #some code
except Exception as e:
    print e

这将自动捕获任何异常。假设您想在 '#some code"...

中进行简单的划分
variable = int(raw_input('Input: '))
result = 50/variable

现在,假设有人输入 0,或者一个字母,甚至是一个字符串...据我所知,由于我们使用了通用异常捕获,所有这些都将得到处理,因此代码将跳转到除了块,避免崩溃。


在 C++ 中,您必须在一个 IF 语句中检查输入是否为数字,然后在另一个 IF 语句中检查它是否不为零,如果是这种情况,则抛出相应的异常。

int var = 0, result = 0;

try
    cin >> var;

    if (var == 0)
        throw "Zero Division Error";

    result = 50/var;

catch(...)
    //exception handling code

所有这些(虽然不整洁,而且是一种不好的做法),可以简单地使用纯 IF-ELSE 语句完成,而无需 try-catch 块。但是,在 C++ 中,如果发生任何意外异常,您就完成了。您必须手动处理每个异常,为每种可能的情况添加 throw 语句,而在 python 中,这是自动为您完成的,它甚至会告诉您出了什么问题,以及什么样的异常你的通用变量 'e' 被捕获了。


所以问题是:有没有办法在任何版本的 C++ 中编写 try-catch 块,自动处理任何异常并将其分配给供您打印的通用变量?

因为如果没有,我看不出使用 try-catch 结构的目的,除了让你的代码看起来更整洁更有条理(与 switch 语句相同)。

【问题讨论】:

请注意,C++ 中的异常如果抛出,代价高昂。将它们用于简单的输入验证确实不是一个好习惯,仅将它们用于真正的异常事件。 另请注意,在大多数情况下,当抛出未捕获的异常时,通常意味着存在无法恢复的问题,因此最简单的解决方案是终止。 许多在 Python 中属于异常的动作(例如除以 0)在 C++ 中不是异常。所以,您的问题的答案可能是 使用except Exception 是一种非常糟糕的做法,在这种情况下不是你应该做的。如果您期待ZeroDivisionErrorTypeError,那么您应该明确处理except (ZeroDivisionError, TypeError) as e: 【参考方案1】:

有没有办法在任何版本的 C++ 中编写 try-catch 块,自动处理任何异常并将其分配给通用变量以供您打印?

是的如果您遵循的做法是只抛出从std::exception 公开派生的类类型的异常并覆盖what() 方法,以便它返回带有一些适当错误消息的字符串。然后可以使用以下方法处理任何异常:

try 
    // ...
 catch (std::exception& e) 
    std::cerr << e.what() << std::endl;

例如,你可以这样写一个异常类:

class divide_error : public std::exception 
    const char* what() const 
        return "division by 0";
    
;

C++ 中的异常到底有什么好处这个问题更多是基于意见的,并且已经在其他地方进行了讨论。见When and how should I use exception handling?

【讨论】:

【参考方案2】:

关于像python这样的高级语言“自动”检测异常的事实,这一切都取决于一切都是对象(甚至是简单的整数和字符),并且每个运算符都相应地重载,例如,如果您尝试除以零,解释器(与 C++ 的编译器相反,它简单地执行适当的位操作,使其更快但更基本)将操作作为一个整体预定义的方法,并相应地执行。 重要的是,在 python 本身预定义的那些方法中,已经存在引发相应异常的所有必需检查。

如果您花时间重载所有内容并确保您处理的每个变量实际上都是一个对象,并且它的所有方法和运算符都会进行所有相应的检查,那么抛出一个泛型异常(即确保定义一个默认泛型异常类,派生自 std::exception 类,并覆盖相应的方法以实现您想要的结果,就像@Brian 所说的那样)如果需要,您可以实现几乎相同的结果。

【讨论】:

哦,实际上,这很有意义。但是我想知道是否已经有一个 API 来简化它 我不这么认为,因为从头开始重载 c++ 必须提供的每个基本功能都太复杂了,这就是为什么如果你需要一个有点自动的 try-catch 结构,你应该做适当的重载和覆盖自己,只关心你需要什么,而不是重做整个语言:P

以上是关于C++ 中的通用异常处理的主要内容,如果未能解决你的问题,请参考以下文章

Grails 控制器中的异常处理

Informix 存储过程通用异常处理

深入理解C++中的异常处理机制

C++中的异常处理

RESTEasy中的通用异常处理ExceptionMapper

Java子线程中的异常处理(通用)