现在的位置: 首页 > 综合 > 正文

异常机制与函数调用区别和联系

2013年09月02日 ⁄ 综合 ⁄ 共 1594字 ⁄ 字号 评论关闭

 在查找用来处理被抛出异常的catch ()子句时因为异常而退出, 复合语句和函数定义这个过程被称作栈展开stack unwinding 。随着栈的展开在退出的复合语句和函数定义中

声明的局部变量的生命期也结束了。

C++保证随着栈的展开尽管局部类对象的生命期是因为抛出异常而被结束但是这些局部类对象的析构函数也会被调用。

如果一个程序没有为已被抛出的异常提供

catch 子句该怎么办呢?异常不能够保持在未被处理的状态异常对于一个程序非常重要。它表示程序不能够继续正常执行,如果没有找到处理代码程序就调用C++标准库中定义的函数terminate() ,terminate()的缺省行为是调用abort(), 指示从程序非正常退出, 在大多数情况下调用abort() 已经足够了。但是在某些特殊情况下我们有必要改变由terminate()执行的动作, 即设置terminater()所触发的函数处理方法。

异常处理和函数调用之间的许多相似之处

 

throw 表达式的行为有点像函数调用, 而catch 子句有点像函数定义。 

这两种机制的一个主要区别是: 建立函数调用所需要的全部信息在编译时刻已经获得, 而对异常处理机制则不然。 

C++异常处理要求运行时刻的支持。 例如对于一个普通函数调用通过函数重载解析过程,编译器知道在调用点上哪个函数会被真正调用,但对于异常处理编译器不知道特定的throw 表达式的catch 子句在哪个函数中以及在处理异常之后执行权被转交到哪儿,这些决策必须在运行时刻进行。 当一个异常不存在处理代码时编译器无法通知用户。 这就是为什么terminate()函数存在的原因它是一种运行时刻机制当没有处理代码能够匹配被抛出的异常时由它通知用户

 

 

如果函数抛出了一个没有被列在异常规范中的异常会怎么样?

程序只有在遇到某种不正常情况时异常才会被抛出. 在编译时刻编译器不可能知道在执行时程序是否会遇到这些异常. 因此一个函数的异常规范的违例只能在运行时刻才能被检测出来.

如果函数抛出了一个没有被列在其异常规范中的异常, 则系统调用C++标准库中定义的函数unexpected(). unexpected()的缺省行为是调用terminate().  在某些条件下可能有必要改变unexpected()执行的动作. C++标准库提供了一种机制可让我们改变unexpected()的缺省行为.

空的异常规范保证函数不会抛出任何异常.

例如函数no_problem()保证不会抛出任何异常extern void no_problem() throw();

如果一个函数声明没有指定异常规范, 则该函数可以抛出任何类型的异常,

在被抛出的异常类型与异常规范中指定的类型之间不允许类型转换例. :

此处谈到”test” string(“test”)的区别, 记得有本书提到, string串除了在定义时用string(“”)定义, 其他的地方都是const char*类型。

int convert( int parm ) throw(string)

{

// ...

if ( somethingRather )

// 程序错误:

// convert() 不允许 const char* 型的异常

throw "help!";

}

在函数convert()中的throw 表达式抛出一个C 风格的字符串, 由这个throw 表达式创建

的异常对象的类型为const char* .

通常const char*型的表达式可以被转换成string 类型, 但是异常规范不允许从被抛出的异常类型到异常规范指定的类型之问的转换. 如果convert()抛出该异常, 则调用函数unexpected() . 为了修正这种情况可以如下修改throw 表达式, 显式地把表达式的值转换成string 类型throw string( "help!" );

 

后面会谈到定义unexpected()的动作,  从而进行改变默认的terminate()的调用。

 

抱歉!评论已关闭.