1、抛出异常(也称为抛弃异常)即检测是否产生异常,在C++中,其采用throw语句来实现,如果检测到产生异常,则抛出异常(给后面的检测模块接收)。该语句的格式为:

throw 表达式;

 

 2、 如果在try语句块的程序段中(包括在其中调用的函数)发现了异常,且抛弃了该异常,则这个异常就可以被try语句块后的某个catch语句所捕获并处理,捕获和处理的条件是被抛弃的异常的类型与catch语句的异常类型相匹配。由于C++使用数据类型来区分不同的异常,因此在判断异常时,throw语句中的表达式的值就没有实际意义,而表达式的类型就特别重要。

 

一般来说,throw语句通常与try- catch或try-finally语句一起使用,可以使用throw语句显式引发异常。

 

c++ try_catch

 

1、基础介绍

try

{

//程序中抛出异常

throw value;

}

catch(valuetype v)

{

//例外处理程序段

}

语法小结:throw抛出值,catch接受,当然,throw必须在“try语句块”中才有效。

 

3、

4、try一个函数体,形式如下

void fun(type1,type2) try----try放在函数体后

{

   函数定义

}

catch(typeX){}

这个用法的效果就相当于:

void fun()

{

   try{函数定义}

}

5、throw一个函数体,形式如下:

void fun (); // 能抛出任何类型的异常

void fun () throw(except1,except2,except3)

               // 后面括号里面是一个异常参数表,本例中只能抛出这3中异常

void fun () throw()   // 参数表为空,不能抛出异常

 

问题b:假设fun()中抛出了一个不在“异常参数表”中的异常,会怎么样?

答:调用set_terminate()中设定的终止函数。然而,这只是表面现象,实际上是调用默认的unexpected()函数,然而这个默认的unexpected()调用了set_terminate()中设定的终止函数。可以用set_unexpected()来设置 unexpected,就像set_terminate()一样的用法,但是在设定了新的“unexpected()”之后,就不会再调用 set_terminater中设定的终止函数了。

这个语法是很有用的,因为在用别人的代码时,不知道哪个地方会调用什么函数又会抛出什么异常,用一个异常参数表在申明时限制一下,很实用。

 

 

 

 4、为什么要用throw (自己认为):

c++ try catch 问题 :

try{} catch(…){}

以前都是用try{} catch(…){}来捕获C++中一些意想不到的异常, 今天看了Winhack的帖子才知道,这种方法在VC中其实是靠不住的。例如下面的代码:


  1. try
  2. {
  3. BYTE* pch ;
  4. pch = ( BYTE* )00001234 ;   //给予一个非法地址
  5. *pch = 6 ; //对非法地址赋值,会造成Access Violation 异常
  6. }
  7. catch(...)
  8. {
  9. AfxMessageBox( "catched" ) ;
  10. }


这段代码在debug下没有问题,异常会被捕获,会弹出”catched”的消息框。 但在Release方式下如果选择了编译器代码优化选项,则VC编译器会去搜索try块中的代码, 如果没有找到throw代码, 他就会认为try catch结构是多余的, 给优化掉。 这样造成在Release模式下,上述代码中的异常不能被捕获,从而迫使程序弹出错误提示框退出。

 

在没有throw的时候,linux下 catch(...) 可能捕捉不到系统异常,因为:

   window2000系统下catch(…)能捕获住系统异常, 这完全是它自己的扩展。在C++标准中并没有要求到这一点,它只规定catch(…)必须能捕获程序中所有通过throw语句抛出的异常。因此 程序在linux系统下的运行虽结果也完全是符合C++标准的,但是捕捉不到异常。

 

5、catch(…) 的应用:

 

 

catch(…)能够捕获多种数据类型的异常对象,所以它提供给程序员一种对异常 对象更好的控制手段,使开发的软件系统有很好的可靠性。因此一个比较有经验的程序员通常会这样组织编写它的代码模块,如下:

void Func()

{

try

{

// 这里的程序代码完成真正复杂的计算工作,这些代码在执行过程中

// 有可能抛出DataType1、DataType2和DataType3类型(主要是类型,不是具体值)的异常对象。

}

catch(DataType1& d1)

{

}

catch(DataType2& d2)

{

}

catch(DataType3& d3)

{

}

// 注意上面try block中可能抛出的DataType1、DataType2和DataType3三

// 种类型的异常对象在前面都已经有对应的catch block来处理。但为什么

// 还要在最后再定义一个catch(…) block呢?这就是为了有更好的安全性和

// 可靠性,避免上面的try block抛出了其它未考虑到的异常对象时导致的程

// 序出现意外崩溃的严重后果,而且这在用VC开发的系统上更特别有效,因

// 为catch(…)能捕获系统出现的异常,而系统异常往往令程序员头痛了,现

// 在系统一般都比较复杂,而且由很多人共同开发,一不小心就会导致一个

// 指针变量指向了其它非法区域,结果意外灾难不幸发生了。catch(…)为这种

// 潜在的隐患提供了一种有效的补救措施。

catch(…)

{

}

}