异常处理(c++工具)

异常处理

异常处理的任务

程序编制者不仅要考虑程序没有错误的理想情况,更要考虑程序存在错误时的情况,应该能够尽快地发现错误,消除错误。

程序中常见的错误有两大类: 语法错误运行错误。在编译时,编译系统能发现程序中的语法错误。

有的程序虽然能通过编译,也能投入运行。但是在运行过程中会出现异常,得不到正确的运行结果,甚至导致程序不正常终止,或出现死机现象。这类错误比较隐蔽,不易被发现,往往耗费许多时间和精力。这成为程序调试中的一个难点。

在设计程序时,应当事先分析程序运行时可能出现的各种意外的情况,并且分别制订出相应的处理方法,这就是程序的异常处理的任务。

在运行没有异常处理的程序时,如果运行情况出现异常,由于程序本身不能处理,程序只能终止运行。如果在程序中设置了异常处理机制,则在运行情况出现异常时,由于程序本身已规定了处理的方法,于是程序的流程就转到异常处理代码段处理。用户可以指定进行任何的处理。

需要说明,只要出现与人们期望的情况不同,都可以认为是异常,并对它进行异常处理。因此,所谓异常处理指的是对运行时出现的差错以及其他例外情况的处理


异常处理的方法

在一个小的程序中,可以用比较简单的方法处理异常。但是在一个大的系统中,如果在每一个函数中都设置处理异常的程序段,会使程序过于复杂和庞大。因此,C++采取的办法是: 如果在执行一个函数过程中出现异常,可以不在本函数中立即处理,而是发出一个信息,传给它的上一级(即调用它的函数),它的上级捕捉到这个信息后进行处理。如果上一级的函数也不能处理,就再传给其上一级,由其上一级处理。如此逐级上送,如果到最高一级还无法处理,最后只好异常终止程序的执行。

这样做使异常的发现与处理不由同一函数来完成。好处是使底层的函数专门用于解决实际任务,而不必再承担处理异常的任务,以减轻底层函数的负担,而把处理异常的任务上移到某一层去处理。这样可以提高效率。

C++处理异常的机制是由个部分组成的,即检查(try)、抛出(throw)和捕捉(catch)。把需要检查的语句放在try块中,throw用来当出现异常时发出一个异常信息,而catch则用来捕捉异常信息,如果捕捉到了异常信息,就处理它


通过例子来了解他们的使用方法:


/*例.1 给出三角形的三边a,b,c,求三角形的面积。只有a+b>c,b+c>a,c+a>b时才能构成三角形。设置异常处理,对不符合三角形条件的输出警告信息,不予计算。
*/

//先写出没有异常处理时的程序:
#include <iostream>
#include <cmath>
using namespace std;
int main( )
{double triangle(double,double,double);
 double a,b,c;
 cin>>a>>b>>c;
 while(a>0 && b>0 && c>0)
  {cout<<triangle(a,b,c)<<endl;
   cin>>a>>b>>c;
  }
  return 0;

}

double triangle(double a,double b,double c)
{double area;
 double s=(a+b+c)/2;
 area=sqrt(s*(s-a)*(s-b)*(s-c));
 return area;
}


/*运行情况如下:
6 5 4↙(输入a,b,c的值) 
9.92157             (输出三角形的面积)
1 1.5 2↙          (输入a,b,c的值)
0.726184            (输出三角形的面积)
1 2 1↙            (输入a,b,c的值)
0                   (输出三角形的面积,此结果显然不对,因为不是三角形)
1 0 6↙            (输入a,b,c的值) 
(结束)*/


/*修改程序,在函数traingle中对三角形条件进行检查,如果不符合三角形条件,就抛出一个异常信息,在主函数中的try-catch块中调用traingle函数,检测有无异常信息,并作相应处理。*/

//修改后的程序如下:
#include <iostream>
#include <cmath>
using namespace std;
void main( )
{double triangle(double,double,double);
 double a,b,c;
 cin>>a>>b>>c;
 try//在try块中包含要检查的函数
  {while(a>0 && b>0 && c>0)
    {cout<<triangle(a,b,c)<<endl;
   cin>>a>>b>>c;
    }
  }

 catch(double)                       //用catch捕捉异常信息并作相应处理
  {cout<<″a=″<<a<<″,b=″<<b<<″,c=″<<c<<″,that is not a triangle!″<<endl;}
 cout<<″end″<<endl;
}

double triangle(double a,double b,double c)  //计算三角形的面积的函数
{double s=(a+b+c)/2;
 if (a+b<=c||b+c<=a||c+a<=b) throw a;   //当不符合三角形条件抛出异常信息
 return sqrt(s*(s-a)*(s-b)*(s-c));
}
/*程序运行结果如下:
6 5 4↙(输入a,b,c的值) 
9.92157             (计算出三角形的面积)
1 1.5 2↙          (输入a,b,c的值)
0.726184            (计算出三角形的面积)
1 2 1↙            (输入a,b,c的值)
a=1,b=2,c=1, that is not a triangle!  (异常处理)
end
*/

/*
现在结合程序分析怎样进行异常处理。
(1) 首先把可能出现异常的、需要检查的语句或程序段放在try后面的花括号中。
(2) 程序开始运行后,按正常的顺序执行到try块,开始执行try块中花括号内的语句。如果在执行try块内的语句过程中没有发生异常,则catch子句不起作用,流程转到catch子句后面的语句继续执行。
(3) 如果在执行try块内的语句(包括其所调用的函数)过程中发生异常,则throw运算符抛出一个异常信息。throw抛出异常信息后,流程立即离开本函数,转到其上一级的函数(main 函数)。
throw抛出什么样的数据由程序设计者自定,可以是任何类型的数据。

(4) 这个异常信息提供给try-catch结构,系统会寻找与之匹配的catch子句。
(5) 在进行异常处理后,程序并不会自动终止,继续执行catch子句后面的语句。
由于catch子句是用来处理异常信息的,往往被称为catch异常处理块或catch异常处理器。

下面讲述异常处理的语法。
throw语句一般是由throw运算符和一个数据组成的,其形式为
throw 表达式;
try-catch的结构为
try
      {被检查的语句} 
catch(异常信息类型[变量名])
      {进行异常处理的语句}

说明:
(1) 被检测的函数必须放在try块中,否则不起作用。
(2) try块和catch块作为一个整体出现,catch块是try-catch结构中的一部分,必须紧跟在try块之后,不能单独使用,在二者之间也不能插入其他语句。但是在一个try-catch结构中,可以只有try块而无catch块。即在本函数中只检查而不处理,把catch处理块放在其他函数中。
(3) try和catch块中必须有用花括号括起来的复合语句,即使花括号内只有一个语句,也不能省略花括号。
(4) 一个try-catch结构中只能有一个try块,但却可以有多个catch块,以便与不同的异常信息匹配。

(5) catch后面的圆括号中,一般只写异常信息的类型名,如
catch(double)
catch只检查所捕获异常信息的类型,而不检查它们的值。因此如果需要检测多个不同的异常信息,应当由throw抛出不同类型的异常信息。
异常信息可以是C++系统预定义的标准类型,也可以是用户自定义的类型(如结构体或类)。如果由throw抛出的信息属于该类型或其子类型,则catch与throw二者匹配,catch捕获该异常信息。
catch还可以有另外一种写法,即除了指定类型名外,还指定变量名,如
catch(double d)

此时如果throw抛出的异常信息是double型的变量a,则catch在捕获异常信息a的同时,还使d获得a的值,或者说d得到a的一个拷贝。什么时候需要这样做呢?有时希望在捕获异常信息时,还能利用throw抛出的值,如
catch(double d)
  {cout<<″throw ″<<d;}
这时会输出d的值(也就是a值)。当抛出的是类对象时,有时希望在catch块中显示该对象中的某些信息。这时就需要在catch的参数中写出变量名(类对象名)。
(6) 如果在catch子句中没有指定异常信息的类型,而用了删节号“…”,则表示它可以捕捉任何类型的异常信息,如

catch(…) {cout<<″OK″<<endl;}
它能捕捉所有类型的异常信息,并输出″OK″。
这种catch子句应放在trycatch结构中的最后,相当于“其他”。如果把它作为第一个catch子句,则后面的catch子句都不起作用。
(7) trycatch结构可以与throw出现在同一个函数中,也可以不在同一函数中。当throw抛出异常信息后,首先在本函数中寻找与之匹配的catch,如果在本函数中无trycatch结构或找不到与之匹配的catch,就转到离开出现异常最近的trycatch结构去处理。

(8) 在某些情况下,在throw语句中可以不包括表达式,如
throw;
表示“我不处理这个异常,请上级处理”。
(9) 如果throw抛出的异常信息找不到与之匹配的catch块,那么系统就会调用一个系统函数terminate,使程序终止运行。

*/



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值