如何在C ++中捕获“任何”异常?

时间:2012-08-29 03:45:43

标签: c++ exception

据我了解,c ++中的所有异常最终都会扩展exception。在Java世界中,无论Exception的类型如何,捕获Exception e都会有效。这是如何在C ++中完成的?

为什么没有捕获此代码段异常中的内容?

try{        
    int z = 34/0;
    cout << "This line should not appear" << endl;
} catch (exception e) {
    cout << "An error has occurred: " << e.what();  // Not executed
}

另外,在C ++中,如何找出导致异常的动作?

4 个答案:

答案 0 :(得分:5)

  

为什么没有捕获此代码段异常?

整数除以0不是标准的c ++异常。所以在这种情况下不会抛出任何异常,你得到的是一个简单的 未定义的行为

某些特定的编译器可能会将此场景映射到特定的异常,您必须检查编译器文档才能找到相同的内容。但是,使用此类功能将是不可移植的,并且您的代码将仅限于您的特定编译器。

在这种情况下你能做的最好的事情就是自己检查错误条件(除数等于零)并明确地抛出异常。

  

此外,在C ++中,如何找出导致异常的操作?

std::exception类专门为此提供方法std::exception::what()

答案 1 :(得分:2)

除以0会导致大多数CPU遵循某种升级过程,这可能被称为异常,信号,中断,陷阱或CPU制造商的行话中的任何内容。这些都没有 - 即使也使用术语“异常” - 与C ++语言异常有任何直接关系。

在C ++中,因为CPU周期和目标代码大小通常很昂贵,要重复测试除以零,内置类型的编译器生成代码不需要进行任何此类检查。在实践中,通常足以相信程序员将编码以避免除以零,在他们有用的分区子集中插入显式检查;考虑这种检查以避免冗余。

如果程序员想要一致的保证检查,他们可以创建一个用户定义类型(一个带有自定义重载运算符的类),可以用来代替内置数字类型,但需要花时间检查除零(或下溢,溢出或开发人员所关注的任何其他问题)并且程序员喜欢这些反应。我认为像JAVA和C#这样的语言缺乏运算符重载,我想这意味着它们不能以这种方式无痛地替换内置类型,需要通过侵入式代码更改来显式调用函数而不是使用直观的数学运算符。

无论如何,由于C ++标准本身没有为被零除的情况指定一些行为,所以如果选择,实现可以自由地提供一些可能有用的行为。这可能会以某种方式包含生成实际的C ++语言异常,但在实践中,它可能在CPU周期和代码大小上过于昂贵而无法证明。也许JAVA是如此缓慢和臃肿无论如何,这样一点额外的检查既不是在这里也不是......? ; - )

假设您使用的是x86系列CPU,除以0通知的术语是“中断”。但是,如果该机器正在运行说UNIX或Linux,则该分区会在操作系统级别产生“信号”,您可以设置信号处理程序以获取问题的通知。

答案 2 :(得分:1)

你写

  

据我了解,c ++中的所有异常最终都会扩展exception

那是错的。 C ++异常可以是任何类型的。使用C ++ 98时,它必须是可复制的,但可能(并且很可能)使用C ++ 11解除了限制。

  

在Java世界中,无论Exception的类型如何,捕获Exception e都会起作用。这是如何在C ++中完成的?

通过一个包罗万象的条款,

catch( ... )

主要的问题是如果你想要有关异常的任何信息,那么在C ++ 98中你必须重新抛出,这不是一种特别有效的方法。截至2012年,您的工具链可能还不支持C ++ 11的异常处理工具。

  

为什么没有捕获此代码段异常中的内容?

因为没有C ++异常。通常,编译器将拒绝编译常量表达式34/0。我想不出除了g ++之外的任何编译器编译它:你实际编译了那段代码吗?

无论如何,如果有人设法编译该代码,那么从标准的C ++角度来看,它只会导致未定义的行为,任何事情都可能发生。如果你很幸运,你会获得signal,但没有任何保证。但是,可以使用特定于平台的功能来捕获此类事件。

答案 3 :(得分:0)

除以零不会在C ++中引发异常。例如,请参阅hereherehere