C++程序运行时的异常处理

开发 后端
C++开发中最头疼的就是运行时的异常处理,判断异常的原因有很多,请看本文为您一一详解。

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

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

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

  try 
  {  
  被检查语句  
  throw 异常  
  }  
  catch(异常类型1)  
  {  
  进行异常处理的语句1  
  }  
  catch(异常类型2)  
  {  
  进行异常处理的语句2  
  }  
  ... 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

  下面我们用示例演示一下异常处理:

#include "stdafx.h"  
#include <iostream>  
template <typename T>  
T Div(T x,T y)  
{  
if(y==0)  
throwy;//抛出异常  
returnx/y;}  
intmain()  
{  
intx=5,y=0;  
doublex1=5.5,y1=0.0;  
try 
{//被检查的语句  
std::cout<<x<<"/"<<y<<"="<<Div(x,y)<<std::endl;  
std::cout<<x1<<"/"<<y1<<"="<<Div(x1,y1)<<std::endl;  
}  
catch(int)//异常类型  
{  
std::cout<<"除数为0,计算错误!"<<std::endl;//异常处理语句  
}  
catch(double)//异常类型  
{  
std::cout<<"除数为0.0,计算错误!"<<std::endl;//异常处理语句  
}  
return0;  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.

  结果:

  看了上述的示例代码,也许有人会问,第二个双精度类型的除法计算也应该抛出异常才对啊,在实际的运行过程中并非如此,其实该双精度类型除法函数根本没有被执行过。以上程序的执行规程为:调用函数Div(x,y)时发生异常,由函数Div中的语句"throw y"抛出异常,并不在往下执行return x/y,接着catch捕获int类型的异常并处理异常,***直接执行"return 0"。因此函数Div(x1,y1)和catch(double){}模块根本没有被执行。如果,我们把y的值改为1,则结果就变成为:

  如果在执行try语句模块时,没有发生异常,则catch语句块不起作用,流程转到其后的语句继续执行。从上述两个结果中可知***次throw抛出的int类型所以找到处理该类型的catch,而第二次是抛出double类型所找到的是处理double类型的catch。

  下面对异常处理补充几点:(1)try和catch块中必须要用花括号括起来,即使花括号内只有一个语句也不能省略花括号;(2)try和catch必须成对出现,一个try_catch结果中只能有一个try块,但可以有多个catch块,以便与不同的异常信息匹配;(3)如果在catch块中没有指定异常信息的类型,而用删节号"...",则表示它可以捕获任何类型的异常信息;(4)如果throw不包括任何表达式,表示它把当前正在处理的异常信息再次抛出,传给其上一层的catch来处理;(5)C++中一旦抛出一个异常,如果程序没有任何的捕获,那么系统将会自动调用一个系统函数terminate,由它调用abort终止程序

  ***还是一样,我将用一个示例来总结一下今天所讲的内容(开发工具:vs2010): 

#include "stdafx.h"  
#include <iostream>  
template <typename T>  
T Div(T x,T y)  
{  
if(y==0)  
throwy;//抛出异常  
returnx/y;  
}  
intmain(){  
intx=5,y=1;  
doublex1=5.5,y1=0.0;  
try 
{//被检查的语句  
std::cout<<x<<"/"<<y<<"="<<Div(x,y)<<std::endl;  
std::cout<<x1<<"/"<<y1<<"="<<Div(x1,y1)<<std::endl;  
}  
catch(...)//捕获任意类型异常  
{  
try 
{  
std::cout<<"任意类型异常!"<<std::endl;  
throw;//抛出当前处理异常信息给上一层catch  
}  
catch(int)//异常类型  
{  
std::cout<<"除数为0,计算错误!"<<std::endl;//异常处理语句  
}  
catch(double)//异常类型  
{std::cout<<"除数为0.0,计算错误!"<<std::endl;//异常处理语句  
}  
}  
return0;  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.

  结果:

原文链接:http://www.cnblogs.com/CaiNiaoZJ/archive/2011/08/19/2145349.html

责任编辑:彭凡 来源: 博客园
相关推荐

2010-01-27 14:14:48

C++程序运行时间

2024-12-09 13:00:00

C++类型安全

2023-11-21 16:31:51

C++语言

2009-07-20 16:14:39

ASP.NET运行时

2015-07-20 15:44:46

Swift框架MJExtension反射

2024-01-22 13:05:00

C++编程异常处理

2021-03-15 08:33:01

CC++动态库

2024-03-21 09:15:58

JS运行的JavaScrip

2011-12-27 09:39:12

C#运行时

2020-12-07 13:31:43

GoMutex开发者

2010-01-27 15:36:54

C++异常处理

2021-09-11 15:38:23

容器运行镜像开放

2019-07-12 09:30:12

DashboardDockerDNS

2023-08-21 09:37:57

MySQL工具MariaDB

2023-08-27 21:07:02

2024-01-29 08:07:42

FlinkYARN架构

2020-07-15 08:11:05

Linuxc++程序

2010-01-27 15:29:45

C++异常处理

2021-08-27 00:21:19

JSJust源码

2023-08-29 08:20:35

Kubernete跨云容器
点赞
收藏

51CTO技术栈公众号