当前位置:   article > 正文

C++和C中常见的异常处理_c++异常处理的应用常见

c++异常处理的应用常见

程序中的错误分为编译时的错误和运行时的错误。编译时的错误主要是语法错误,比如:句尾没有加分号,括号不匹配,关键字错误等,这类错误比较容易修改,因为编译系统会指出错误在第几行,什么错误。而运行时的错误则不容易修改,因为其中的错误是不可预料的,或者可以预料但无法避免的,比如内存空间不够,或者在调用函数时,出现数组越界等错误。如果对于这些错误没有采取有效的防范措施,那么往往会得不到正确的运行结果,程序不正常终止或严重的会出现死机现象。我们把程序运行时的错误统称为异常,对异常处理称为异常处理。C++中所提供的异常处理机制结构清晰,在一定程度上可以保证程序的健壮性。


一、C++中异常处理

C++中处理异常的过程是这样的:在执行程序发生异常,可以不在本函数中处理,而是抛出一个错误信息,把它传递给上一级的函数来解决,上一级解决不了,再传给其上一级,由其上一级处理。如此逐级上传,直到最高一级还无法处理的话,运行系统会自动调用系统函数terminate,由它调用abort终止程序。这样的异常处理方法使得异常引发和处理机制分离,而不在同一个函数中处理。这使得底层函数只需要解决实际的任务,而不必过多考虑对异常的处理,而把异常处理的任务交给上一层函数去处理。


C++的异常处理机制有3部分组成:try(检查),throw(抛出),catch(捕获)。把需要检查的语句放在try模块中,检查语句发生错误,throw抛出异常,发出错误信息,由catch来捕获异常信息,并加以处理。一般throw抛出的异常要和catch所捕获的异常类型所匹配。异常处理的一般格式为:

  1. try{
  2. <span style="white-space:pre"> </span>被检查语句
  3.     throw 异常
  4. }
  5. catch(异常类型1){
  6. <span style="white-space:pre"> </span>进行异常处理的语句1
  7. }
  8. catch(异常类型2){
  9.     进行异常处理的语句2
  10. }
  11. ...
如果在执行try语句模块时,没有发生异常,则catch语句块不起作用,流程转到其后的语句继续执行。


对异常处理注意几点:

(1)try和catch块中必须要用花括号括起来,即使花括号内只有一个语句也不能省略花括号;

(2)try和catch必须成对出现,一个try_catch结果中只能有一个try块,但可以有多个catch块,以便与不同的异常信息匹配;

(3)如果在catch块中没有指定异常信息的类型,而用删节号"...",则表示它可以捕获任何类型的异常信息;

(4)如果throw不包括任何表达式,表示它把当前正在处理的异常信息再次抛出,传给其上一层的catch来处理;

(5)C++中一旦抛出一个异常,如果程序没有任何的捕获,那么系统将会自动调用一个系统函数terminate,由它调用abort终止程序;

(6)遇到异常,不会执行之后操作。除非有finally语句,执行return及以后的操作,然后执行finally语句块,若finally语句有return,则覆盖之前的return。


举个栗子:

  1. #include <iostream>
  2. using namespace std;
  3. template<typename T>
  4. T Div(T x,T y){
  5. if(y==0)
  6. throw y;
  7. return x/y;
  8. }
  9. int main(){
  10. int i_x=5, i_y=1;
  11. double d_x=5.5, d_y=0.0;
  12. try{
  13. cout << i_x << "/" << i_y << "=" << Div(i_x,i_y) << endl;
  14. cout << d_x << "/" << d_y << "=" << Div(d_x,d_y) << endl;
  15. cout << "异常后还能执行" << endl;
  16. }
  17. catch(...){ //捕获任何异常
  18. try{
  19. cout << "捕获任意异常类型" << endl;
  20. throw; //抛出当前处理异常信息给上一层catch
  21. }
  22. catch(int){
  23. cout << "除数为0!" << endl;
  24. }
  25. catch(double){
  26. cout << "除数为0.0!" << endl;
  27. }
  28. }
  29. system("pause");
  30. return 0;
  31. }

输出为:



调用函数Div(x,y)时发生异常,由函数Div中的语句"throw y"抛出异常,并不在往下执行cout << "异常后还能执行" << endl;,接着catch捕获...任意类型的异常,然后throw把当前异常继续抛出,传给上一层catch,直到catch(double)捕获到,最后直接执行"return 0"。


二、C语言的中异常处理

1.使用标准C库提供了abort()和exit()两个函数,它们可以强行终止程序的运行,其声明处于<stdlib.h>头文件中。

2.使用assert(断言)宏调用,位于头文件<assert.h>中,当程序出错时,就会引发一个abort()。


使用exit()函数进行异常终止:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. double diva(double num1,double num2) //两数相除函数
  4. {
  5. double re;
  6. re=num1/num2;
  7. return re;
  8. }
  9. int main()
  10. {
  11. double a,b,result;
  12. printf("请输入第一个数字:");
  13. scanf("%lf",&a);
  14. printf("请输入第二个数字:");
  15. scanf("%lf",&b);
  16. if(0==b) //如果除数为0终止程序
  17. exit(EXIT_FAILURE);
  18. result=diva(a,b);
  19. printf("相除的结果是: %.2lf\n",result);
  20. return 0;
  21. }
exit的函数原型:void exit(int)由此,我们也可以知道EXIT_FAILURE宏应该是一个整数,exit()函数的传递参数是两个宏,一个是刚才看到的EXIT_FAILURE,还有一个是EXIT_SUCCESS从字面就可以看出一个是出错后强制终止程序,而一个是程序正常结束。他们的定义是:
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1

当出现异常的时候,程序是终止了,但是我们并没有捕获到异常信息。


使用exit()函数进行异常终止:

assert()是一个调试程序时经常使用的宏,切记,它不是一个函数,在程序运行时它计算括号内的表达式,如果表达式为FALSE  (0),  程序将报告错误,并终止执行。如果表达式不为0,则继续执行后面的语句。这个宏通常原来判断程序中是否出现了明显非法的数据,如果出现了终止程序以免导致严重后果,同时也便于查找错误。   

另外需要注意的是:assert只有在Debug版本中才有效,如果编译为Release版本则被忽略。
我们就前面的问题,使用assert断言进行异常终止操作:构造可能出现出错的断言表达式:assert(number!=0)这样,当除数为0的时候,表达式就为false,程序报告错误,并终止执行。

代码如下:

  1. #include <stdio.h>
  2. #include <assert.h>
  3. double diva(double num1,double num2) //两数相除函数
  4. {
  5. double re;
  6. re=num1/num2;
  7. return re;
  8. }
  9. int main()
  10. {
  11. printf("请输入第一个数字:");
  12. scanf("%lf",&a);
  13. printf("请输入第二个数字:");
  14. scanf("%lf",&b);
  15. assert(0!=b); //构造断言表达式,捕获预期异常错误
  16. result=diva(a,b);
  17. printf("相除的结果是: %.2lf\n",result);
  18. return 0;
  19. }



声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/714941
推荐阅读
相关标签
  

闽ICP备14008679号