第十章异常处理 异常处理机制是用于管理程序运行期间出现的非正常情况 的一种结构化方法 本章主要内容 异常的概念 2.异常的捕获与处理
15:26:27 第十章 异常处理 ➢异常处理机制是用于管理程序运行期间出现的非正常情况 的一种结构化方法 本章主要内容 1. 异常的概念 2. 异常的捕获与处理
5:26:7 §1异常的概念 >异常指程序运行期间出现的不正常的情况,与程序的错误 是相关的概念 程序的错误 编译错误:语法错误 ≯运行结果错误:语义错误 >异常错误(bug) 大多数情况下,程序能够正常运行且能得出正确结果,只 在极少数极端情况下,程序无法正常运行或运行结果不正 确
15:26:27 §1 异常的概念 ➢异常指程序运行期间出现的不正常的情况,与程序的错误 是相关的概念 ➢程序的错误 ➢编译错误:语法错误 ➢运行结果错误:语义错误 ➢异常错误(bug) 大多数情况下,程序能够正常运行且能得出正确结果,只 在极少数极端情况下,程序无法正常运行或运行结果不正 确
5:26:7 传统的处理方法:就地处理 >在程序中可能引起问题的地方进行判断,如果条件成立就 马上处理 一般模式为:if(条件){处理语句} 6]: int spInt=new int [100001 if (pInt==NULL) cout<<“ Cannot allocate memory”<<endl; exit(O) ese{正常功能语句;} 存在的问题: 1.类或函数创建者无法确定客户程序员想如何处理该异常 2.客户程序员知道如何处理该异常,却没有机会处理 3.错误处理代码掺杂于功能实现代码中,降低了可读性
15:26:27 ➢传统的处理方法:就地处理 ➢在程序中可能引起问题的地方进行判断,如果条件成立就 马上处理 例:int *pInt=new int[10000]; if(pInt==NULL) { cout << “Cannot allocate memory” << endl; exit(0); } else{ 正常功能语句;} 存在的问题: 1.类或函数创建者无法确定客户程序员想如何处理该异常 2.客户程序员知道如何处理该异常,却没有机会处理 3.错误处理代码掺杂于功能实现代码中,降低了可读性 ➢一般模式为:if(条件){处理语句}
5;26:7 §2异常的捕获与处理 >C++的异常处理通过 throw、try和 catch3个关键字实现 一般处理模式为 函数或类的创建者在被调用函数中检测到异常条件成立, 用 throw抛出一个异常;在客户程序员写的上层主调函数中 使用try检测该函数调用是否引发异常,被检测到的各种异 常由 catch捕获并作相应处理
15:26:27 §2 异常的捕获与处理 ➢C++的异常处理通过throw、try 和 catch 3个关键字实现 ➢一般处理模式为 函数或类的创建者在被调用函数中检测到异常条件成立, 用throw抛出一个异常;在客户程序员写的上层主调函数中 使用try检测该函数调用是否引发异常,被检测到的各种异 常由catch捕获并作相应处理
5:26:7 throw语句的一般形式为 throw表达式; 其中表达式表示一个异常的值,可以是任意类型的对象 异常检测与捕获处理的一般形式为 try //语块 catch(参数声明n) catch(参数声明1) //异常处理n /异常处理1 catch(. catch(参数声明2) //异常处理2 //异常处理n+1 参数声明的形式为: 类型参数或类型&参数
15:26:27 ➢throw语句的一般形式为 throw 表达式; 其中 表达式 表示一个异常的值,可以是任意类型的对象 ➢异常检测与捕获处理的一般形式为 try{ //语句块 } catch(参数声明1) {//异常处理1 } catch(参数声明2) {//异常处理2 } … catch(参数声明n) { //异常处理n } catch(…) { //异常处理n+1 } 参数声明的形式为: 类型 参数 或 类型& 参数
5:26:7 说明: 一个try语句可以与多个 catch语句配套使用 若抛出异常的类型与 catch后括号中说明的数据类型相匹 配,则执行该 catch语句 若异常被捕获,则 catch后括号中的参数将接收抛出异常 时传递过来的值 异常的匹配与 catch语句的顺序有关,只要找到一个匹配 异常类型的 catch,则其它的 catch语句都被忽略 若 catch语句不带参数,则括号内用省略号“”表示该 catch语句捕获所有类型的异常 有多个 catch语句时,带有省略号的 catch语句应放在最后 一旦try检测到异常且与某个 catch语句匹配,则try块中 引发异常的语句后面的语句不再执行 个 catch语句块执行后,跳到所有 catch块之后执行
15:26:27 说明: ➢一个try语句可以与多个catch语句配套使用 ➢若抛出异常的类型与catch后括号中说明的数据类型相匹 配,则执行该catch语句 ➢若异常被捕获,则catch后括号中的参数将接收抛出异常 时传递过来的值 ➢异常的匹配与catch语句的顺序有关,只要找到一个匹配 异常类型的catch,则其它的catch语句都被忽略 ➢若catch语句不带参数,则括号内用省略号“…”表示该 catch语句捕获所有类型的异常 ➢有多个catch语句时,带有省略号的catch语句应放在最后 ➢一旦try检测到异常且与某个catch语句匹配,则try块中 引发异常的语句后面的语句不再执行 ➢一个catch语句块执行后,跳到所有catch块之后执行
5:26:7 >例:处理除数为0的简单异常 double div (double, double); void maino[ double result. try t result=Div(1, 2): cout<<1/2=<<result<<end 1 result=Div(5, 0): cout<<5/0="<<result<<end 1: result=Div(10, 3): cout<< 10/3=<<result<<end1; catch (double e)i cout < Divided by zero << end1; cout < main function is over. << endl. double div double a, double b)i if b==0 throw 0.0 return a/ b
15:26:27 ➢例:处理除数为0的简单异常 double Div(double,double); void main(){ double result; try{ result=Div(1,2); cout<<"1/2 = "<<result<<endl; result=Div(5,0); cout<<"5/0 = "<<result<<endl; result=Div(10,3);cout<<"10/3 = "<<result<<endl; } catch (double e){ cout << "Divided by zero" << endl; cout << "main function is over." << endl; } } double Div(double a,double b){ if (b==0) throw 0.0; return a/b; }
5:26:7 例:不同类型的异常测试 int test(char *p, double e, int a) int f =1 try( if(*p>=0′&*p20000)throw e: if(a)throw a catch char s) [f=0; cout < "password error: < s < end1 catch(double e) If =0; cout < earnings error: < e << end1 catch(int a) If =0; cout < "age error: < a << end1 return f
15:26:27 例:不同类型的异常测试 int test(char *p,double e,int a){ int f = 1; try{ if(*p>='0' && *p20000)throw e; if(a70)throw a; } catch(char s) {f=0;cout << "password error: " << s << endl;} catch(double e) {f = 0;cout << "earnings error: " << e << endl;} catch(int a) {f = 0;cout << "age error: " << a << endl;} return f; }
5:26:7 例:不同类型的异常测试(续) void maino i char pas sword [8 double earnings; nt age; cout > password > earnings >>age, if (test(password earnings, age)) cout < password < < earnings < 6 < age < endl
15:26:27 例:不同类型的异常测试(续) void main(){ char password[8]; double earnings; int age; cout > password >> earnings >> age; if(test(password,earnings,age)) cout << password << " " << earnings << " “ << age << endl; }
15:26:27 带有异常说明的函数原型 若一个函数抛出异常,调用该函数时必须了解该函数抛出 异常的类型,以便在主调函数中加以处理 在声明函数时可以在函数原型上显式指定该函数能够抛出 的异常类型 1.抛出指定类型的异常 T funName (parameterList) throw(T1, T2,., Tn) 2.不抛出异常 T funName (parameterList) throw() 3.抛出任意类型的异常 T funName(parameterList)
15:26:27 ➢带有异常说明的函数原型 ➢若一个函数抛出异常,调用该函数时必须了解该函数抛出 异常的类型,以便在主调函数中加以处理 ➢在声明函数时可以在函数原型上显式指定该函数能够抛出 的异常类型 1.抛出指定类型的异常 T funName(parameterList) throw(T1,T2,…,Tn); 2.不抛出异常 T funName(parameterList) throw( ); 3.抛出任意类型的异常 T funName(parameterList);