我们通常希望自己编写的程序能够在异常的情况下也能作出相应的处理,而不至于程序莫名其妙地中断或者中止运行了。在设计程序时应充分考虑各种异常情况,并加以处理。
在C++中,一个函数能够检测出异常并且将异常返回,这种机制称为抛出异常。当抛出异常后,函数调用者捕获到该异常,并对该异常进行处理,我们称之为异常捕获。
C++新增throw关键字用于抛出异常,新增catch关键字用于捕获异常,新增try关键字尝试捕获异常。通常将尝试捕获的语句放在 try{ } 程序块中,而将异常处理语句置于 catch{ } 语句块中。
异常处理的基本语法如下所述。首先说一下抛出异常的基本语法:
throw 表达式;
抛出异常由throw关键字加上一个表达式构成。抛出异常后需要捕获异常以及异常处理程序,其基本语法如下:
1 try 2 { 3 //可能抛出异常的语句 4 } 5 catch (异常类型1) 6 { 7 //异常类型1的处理程序 8 } 9 catch (异常类型2) 10 { 11 //异常类型2的处理程序 12 } 13 // …… 14 catch (异常类型n) 15 { 16 //异常类型n的处理程序 17 }
一、一个简单的例子
首先通过一个简单的例子来熟悉C++ 的 try/catch/throw(可根据单步调试来熟悉,try catch throw部分是如何运行的):
1 #include <stdlib.h> 2 #include "iostream" 3 using namespace std; 4 5 double fuc(double x, double y) //定义函数 6 { 7 if(y==0) 8 { 9 throw y; //除数为0,抛出异常 10 } 11 return x/y; //否则返回两个数的商 12 } 13 14 int _tmain(int argc, _TCHAR* argv[]) 15 { 16 double res; 17 try //定义异常 18 { 19 res=fuc(2,3); 20 cout<<"The result of x/y is : "<<res<<endl; 21 res=fuc(4,0); //出现异常 22 } 23 catch(double) //捕获并处理异常 24 { 25 cerr<<"error of dividing zero.\n"; 26 exit(1); //异常退出程序 27 } 28 return 0; 29 }
catch 的数据类型需要与throw出来的数据类型相匹配的。
二、catch(...)的作用
catch(…)能够捕获多种数据类型的异常对象,所以它提供给程序员一种对异常对象更好的控制手段,使开发的软件系统有很好的可靠性。因此一个比较有经验的程序员通常会这样组织编写它的代码模块,如下:
1 void Func() 2 { 3 try 4 { 5 // 这里的程序代码完成真正复杂的计算工作,这些代码在执行过程中 6 // 有可能抛出DataType1、DataType2和DataType3类型的异常对象。 7 } 8 catch(DataType1& d1) 9 { 10 } 11 catch(DataType2& d2) 12 { 13 } 14 catch(DataType3& d3) 15 { 16 } 17 /********************************************************* 18 注意上面try block中可能抛出的DataType1、DataType2和DataType3三 19 种类型的异常对象在前面都已经有对应的catch block来处理。但为什么 20 还要在最后再定义一个catch(…) block呢?这就是为了有更好的安全性和 21 可靠性,避免上面的try block抛出了其它未考虑到的异常对象时导致的程 22 序出现意外崩溃的严重后果,而且这在用VC开发的系统上更特别有效,因 23 为catch(…)能捕获系统出现的异常,而系统异常往往令程序员头痛了,现 24 在系统一般都比较复杂,而且由很多人共同开发,一不小心就会导致一个 25 指针变量指向了其它非法区域,结果意外灾难不幸发生了。catch(…)为这种 26 潜在的隐患提供了一种有效的补救措施。 27 *********************************************************/ 28 29 catch(…) 30 { 31 } 32 }
三、异常中采用面向对象的处理
首先看下面的例子:
1 void OpenFile(string f) 2 { 3 try 4 { 5 // 打开文件的操作,可能抛出FileOpenException 6 } 7 catch(FileOpenException& fe) 8 { 9 // 处理这个异常,如果这个异常可以很好的得以恢复,那么处理完毕后函数 10 // 正常返回;否则必须重新抛出这个异常,以供上层的调用函数来能再次处 11 // 理这个异常对象 12 int result = ReOpenFile(f); 13 if (result == false) throw; 14 } 15 } 16 17 void ReadFile(File f) 18 { 19 try 20 { 21 // 从文件中读数据,可能抛出FileReadException 22 } 23 catch(FileReadException& fe) 24 { 25 // 处理这个异常,如果这个异常可以很好的得以恢复,那么处理完毕后函数 26 // 正常返回;否则必须重新抛出这个异常,以供上层的调用函数来能再次处 27 // 理这个异常对象 28 int result = ReReadFile(f); 29 if (result == false) throw; 30 } 31 } 32 33 void WriteFile(File f) 34 { 35 try 36 { 37 // 往文件中写数据,可能抛出FileWriteException 38 } 39 catch(FileWriteException& fe) 40 { 41 // 处理这个异常,如果这个异常可以很好的得以恢复,那么处理完毕后函数 42 // 正常返回;否则必须重新抛出这个异常,以供上层的调用函数来能再次处理这个异常对象 43 int result = ReWriteFile(f); 44 if (result == false) throw; 45 } 46 } 47 48 void Func() 49 { 50 try 51 { 52 // 对文件进行操作,可能出现FileWriteException、FileWriteException 53 // 和FileWriteException异常 54 OpenFile(…); 55 ReadFile(…); 56 WriteFile(…); 57 } 58 // 注意:FileException是FileOpenException、FileReadException和FileWriteException 59 // 的基类,因此这里定义的catch(FileException& fe)能捕获所有与文件操作失败的异 60 // 常。 61 catch(FileException& fe) 62 { 63 ExceptionInfo* ef = fe.GetExceptionInfo(); 64 cout << “操作文件时出现了不可恢复的错误,原因是:”<< fe << endl; 65 } 66 }
转自:https://www.cnblogs.com/xiaojianliu/articles/8900795.html
https://blog.csdn.net/xueluowutong/article/details/81257654
thanks a lot~