版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、1-1 知识回顾知识回顾 I/OI/O流的概念流的概念 输出流输出流 输入流输入流 异常处理异常处理 第八章第八章 理解异常处理的概念理解异常处理的概念 掌握异常处理的实现掌握异常处理的实现 掌握异常处理中对象的构造与析构掌握异常处理中对象的构造与析构 理解名字空间的概述理解名字空间的概述 本章目标本章目标 异常处理是异常处理是C+C+语言中重要的错误处理机制,语言中重要的错误处理机制, 是提高程序容错性的一种手段。异常处理主要是提高程序容错性的一种手段。异常处理主要 针对程序运行时出现的各种异常情况,提供发针对程序运行时出现的各种异常情况,提供发 现,捕获异常的手段,并尽量减少异常对程序现,
2、捕获异常的手段,并尽量减少异常对程序 运行的影响。运行的影响。 有的程序虽然经过编译、连接成为可以运行的程有的程序虽然经过编译、连接成为可以运行的程 序,但在运行过程中难免会出现各种各样的问题序,但在运行过程中难免会出现各种各样的问题 ,即使对那些所谓能,即使对那些所谓能“正常运行正常运行”的程序而言也的程序而言也 是如此。是如此。 程序中潜在的异常问题程序中潜在的异常问题 提出问题提出问题 示例:示例: #include #include using namespace std; int main() float a,b,c; double x1,x2; cout请输入一元二次方程的系数请输
3、入一元二次方程的系数a、b和和c的值的值:endl; couta; coutb; coutc; x1=(-b+sqrt(b*b-4*a*c)/(2*a); x2=(-b-sqrt(b*b-4*a*c)/(2*a); cout方程的实根是方程的实根是:x1=x1endl; cout方程的实根是方程的实根是:x2=x2endl; return 0; 从上面例子可以看出:能够从上面例子可以看出:能够“正常运行正常运行”的程序可能的程序可能 存在着许多潜在的存在着许多潜在的“隐患隐患”。程序运行可以检测到的。程序运行可以检测到的 一些非正常情况称为异常(一些非正常情况称为异常(exception)。)
4、。 如除数为如除数为0、数组越界访问、内存空间不够、输入、数组越界访问、内存空间不够、输入/输输 出不正常(文件找不到、输入数据类型错等)等。出不正常(文件找不到、输入数据类型错等)等。 异常是程序错误一种形式。异常是程序错误一种形式。 分析问题分析问题 程序中的错误按性质可分为语法错误、逻辑错误程序中的错误按性质可分为语法错误、逻辑错误 和异常和异常3种。种。 一般来说,异常的检测和处理要完成下列任务之一般来说,异常的检测和处理要完成下列任务之 一:一: (1)让)让“用户用户”知道程序出现了异常,并退出知道程序出现了异常,并退出 程序。程序。 (2)让)让“用户用户”知道程序出现了异常,允
5、许知道程序出现了异常,允许“ 用户用户”选择继续使用程序。选择继续使用程序。 (3)在程序发生异常时,能够在不打扰)在程序发生异常时,能够在不打扰“用户用户 ”的情况下继续程序的运行。的情况下继续程序的运行。 C+C+语言异常处理机制的基本思想是将异常的检测与处理语言异常处理机制的基本思想是将异常的检测与处理 分离。当在一个函数体中检测到异常条件存在,但无法确分离。当在一个函数体中检测到异常条件存在,但无法确 定相应的处理方法时,将引发一个异常,并由函数直接或定相应的处理方法时,将引发一个异常,并由函数直接或 间接调用检测并处理这个异常。间接调用检测并处理这个异常。 这一基本思想用这一基本思想
6、用3 3个保留字实现:个保留字实现:throwthrow、trytry和和catchcatch。在。在 一般情况下,被调用函数直接检测到异常条件的存在并使一般情况下,被调用函数直接检测到异常条件的存在并使 用用throwthrow引发一个异常(注意,引发一个异常(注意,C+C+语言的异常是由程序员语言的异常是由程序员 控制引发的,而不是由计算机硬件或程序运行环境控制的控制引发的,而不是由计算机硬件或程序运行环境控制的 );在上层调用函数中使用);在上层调用函数中使用trytry检测函数调用是否引发异检测函数调用是否引发异 常,检测到的各种异常由常,检测到的各种异常由catchcatch捕获并作
7、相应处理。捕获并作相应处理。 异常处理实现异常处理实现 在环境中,为了使用异常处理机制,需要进行如下设置(在环境中,为了使用异常处理机制,需要进行如下设置( 默认设置):默认设置): (1)选择菜单中的)选择菜单中的project。 (2)在弹出的下拉菜单中选择)在弹出的下拉菜单中选择Setting命令,出现命令,出现 Settings对话框。对话框。 (3)打开)打开C/C+选项卡。选项卡。 (4)在)在Category中选择中选择 C+ Language。 (5)选中)选中Enable exception handling复选框。复选框。 在在C+程序中,任何需要检测异常的语句(程序中,任
8、何需要检测异常的语句( 包括函数调用)都必须在包括函数调用)都必须在try语句块中执行,语句块中执行, 异常必须由紧跟着异常必须由紧跟着try语句后面的语句后面的catch语句来语句来 捕获并处理。因而,捕获并处理。因而,try与与catch总是结合使用总是结合使用 。 1、异常处理的语法、异常处理的语法 throw、 try和和catch语句的一般语法如下:语句的一般语法如下: throw 表达式;表达式; try /try语句块语句块 catch(类型类型1 参数参数1) /针对类型针对类型1的异常处理的异常处理 catch(类型类型2 参数参数2) /针对类型针对类型1的异常处理的异常处
9、理 . catch(类型(类型n 参数参数n) /针对类型针对类型1的异常处理的异常处理 异常处理的执行过程如下:异常处理的执行过程如下: (1 1)控制通过正常的顺序执行到达)控制通过正常的顺序执行到达trytry语句,然后执行语句,然后执行trytry块内的块内的 保护段。保护段。 (2 2)如果在保护段执行期间没有引起异常,那么跟在)如果在保护段执行期间没有引起异常,那么跟在trytry块后的块后的 catchcatch子句就不执行,程序从异常被抛掷的子句就不执行,程序从异常被抛掷的trytry块后跟随的最后一个块后跟随的最后一个 catchcatch子句后面的语句继续执行下去。子句后面
10、的语句继续执行下去。 (3 3)如果在保护段执行期间或在保护段调用的任何函数中(直接)如果在保护段执行期间或在保护段调用的任何函数中(直接 或间接的调用)有异常被抛掷,则从通过或间接的调用)有异常被抛掷,则从通过throwthrow运算数创建的对象运算数创建的对象 中创建一个异常对象(可能包含一个复制构造函数)。中创建一个异常对象(可能包含一个复制构造函数)。 (4 4)如果匹配的处理器未找到,则运行函数)如果匹配的处理器未找到,则运行函数terminateterminate将被自动调将被自动调 用,而函数用,而函数terminateterminate的默认功能是调用的默认功能是调用abort
11、abort终止程序。终止程序。 (5 5)如果找到了一个匹配的)如果找到了一个匹配的catchcatch处理程序,且它通过值进行捕获处理程序,且它通过值进行捕获 ,则其形参通过复制异常对象进行初始化。,则其形参通过复制异常对象进行初始化。 示例示例1: #include void main() char *buf; try buf=new char512; if(buf=0) throw 内存分配错误内存分配错误!; cout内存分配成功内存分配成功!endl; catch(char *str) cout异常引发异常引发:strendl; 示例示例2: #include int fun(int
12、); void main() try cout4!=fun(4)endl; cout-2!=fun(-2)endl; cout5!=fun(5); catch (int n) coutn=n不能计算不能计算n!endl; cout程序执行结束程序执行结束.endl; int fun(int n) if(n=0) throw n; int s=1; for(int i=1;i=n;i+) s*=i; return s; catch处理程序的出现次序很重要,因为在一个处理程序的出现次序很重要,因为在一个try块中,异常处理块中,异常处理 程序是按照它出现的次序检查的。只要找到一个匹配的异常类型,程
13、序是按照它出现的次序检查的。只要找到一个匹配的异常类型, 后面的异常处理都将被忽略。后面的异常处理都将被忽略。 示例示例3: #include void fun(int code) try if(code=0) throw code; /引发引发int类型的异常类型的异常 if(code=1) throw x; /引发引发char类型的异常类型的异常 if(code=2) throw 12.345; /引发引发double类型的类型的 异常异常 catch(int n) cout捕获整数类型:捕获整数类型:nendl; catch(char c) cout捕获字符类型:捕获字符类型:cendl
14、; catch(double d) cout捕获双精度类型:捕获双精度类型:dendl; return; void main() fun(0); fun(1); fun(2); 程序中同时列出多个程序中同时列出多个catch语句时,将以语句时,将以catch语句在程序中出现语句在程序中出现 的次序作类型匹配,并且只有一个匹配的的次序作类型匹配,并且只有一个匹配的catch语句被执行,其语句被执行,其 他的他的catch语句将被忽略。语句将被忽略。 catch(.)是一个特殊的捕获语句,可以捕获任何异常,因而在是一个特殊的捕获语句,可以捕获任何异常,因而在 任何情况下其他任何情况下其他catch
15、子句都不被检查。所以,子句都不被检查。所以,catch(.)应该放应该放 在最后。在中,若在最后。在中,若catch(.)不是放在所有不是放在所有catch(.)语句的最后语句的最后 ,则会出现编译错误。,则会出现编译错误。 2、捕获异常、捕获异常 示例示例1: #include void fun(int code) try if(code=0) throw code; /引发引发int类型的异常类型的异常 if(code=1) throw x; /引发引发char类型的异常类型的异常 if(code=2) throw 12.345; /引发引发double类型的异常类型的异常 catch(i
16、nt n) cout捕获整数类型捕获整数类型.nendl; catch(.) cout默认捕获默认捕获.endl; return; void main() fun(0); fun(1); fun(2); 从前面异常处理的例子可以看出,调用一个函数时,除从前面异常处理的例子可以看出,调用一个函数时,除 了了解函数的参数与返回值外,还必须了解函数的异常了了解函数的参数与返回值外,还必须了解函数的异常 引发方式,以便设计异常处理程序,应付函数调用过程引发方式,以便设计异常处理程序,应付函数调用过程 中引发的异常。中引发的异常。 异常的引发与捕获已成为函数之间界面的一部分,有必异常的引发与捕获已成为函
17、数之间界面的一部分,有必 要在函数原型中也列出异常引发。要在函数原型中也列出异常引发。 例如:例如: void fun(int i) throw(t1,t2,t3); 3、带有异常声明的函数原型、带有异常声明的函数原型 C+的异常处理机制不仅能够处理各种不同类型的异常,的异常处理机制不仅能够处理各种不同类型的异常, 还具有为抛出异常前构造所有局部对象自动调用析构函数还具有为抛出异常前构造所有局部对象自动调用析构函数 的能力。的能力。 在程序中,找到一个匹配的在程序中,找到一个匹配的catch异常处理后,如果异常处理后,如果catch 子句的异常类型说明是一个值参数,则其初始化方式是复子句的异常
18、类型说明是一个值参数,则其初始化方式是复 制被抛出的异常对象。如果制被抛出的异常对象。如果catch子句的异常类型说明是子句的异常类型说明是 一个引用,则其初始化方式是使该引用指向异常对象。一个引用,则其初始化方式是使该引用指向异常对象。 当当catch子句的异常类型说明参数被初始化后,便于始展子句的异常类型说明参数被初始化后,便于始展 开栈的过程。这包括将从对应的开栈的过程。这包括将从对应的try块开始到异常被抛出之块开始到异常被抛出之 间构造(且尚未析构)的所有自动对象进行析构。析构的间构造(且尚未析构)的所有自动对象进行析构。析构的 次序与构造的次序相反。然后程序从最后一个次序与构造的次
19、序相反。然后程序从最后一个catch处理处理 之后开始恢复执行。之后开始恢复执行。 异常处理中对象的构造与析构异常处理中对象的构造与析构 示例:示例: #include void fun(void); class A public: A() ; A() ; const char *ShowReason() const /异常处理成员函数异常处理成员函数 return 异常在异常在A类中类中; ; class B public: B(); B(); ; B:B() coutB构造函数构造函数endl; B:B() coutB析构函数析构函数endl; void fun() B b; coutfu
20、n():抛掷一个抛掷一个A异常异常endl; throw A(); void main() cout进入进入main()endl; try cout在在try块中调用块中调用fun()endl; fun(); catch( A E) cout在在catch处理器捕获一个异常类型:处理器捕获一个异常类型:; coutE.ShowReason()endl; catch(char *str) cout捕获其他异常:捕获其他异常:strendl; cout返回返回main()endl; 在名字空间中可以放入这样的声明:类、变量(以及它在名字空间中可以放入这样的声明:类、变量(以及它 们的初始化)、函数
21、(以及它们的定义)、模板以及其们的初始化)、函数(以及它们的定义)、模板以及其 他名字空间。从而这些变量或函数都与该名字空间相关他名字空间。从而这些变量或函数都与该名字空间相关 联。联。 名字空间概述名字空间概述 1、名字空间的定义、名字空间的定义 保留字(保留字(namespace)用于定义名字空间。名字空间必)用于定义名字空间。名字空间必 须在程序的全局作用域内定义,不能在函数内或类内部须在程序的全局作用域内定义,不能在函数内或类内部 定义,最外层名字空间的名字必须在程序的全局作用域定义,最外层名字空间的名字必须在程序的全局作用域 惟一。惟一。 名字空间可以分多次定义,即可以先在初始定义中
22、定义名字空间可以分多次定义,即可以先在初始定义中定义 一部分成员,然后在扩展定义中再定义另一部分成员,一部分成员,然后在扩展定义中再定义另一部分成员, 或者再定义初始时声明函数原型。初始定义和扩展定义或者再定义初始时声明函数原型。初始定义和扩展定义 的语法格式相同。的语法格式相同。 保留字保留字using用于声明程序要引入的名字空间成员,或用于声明程序要引入的名字空间成员,或 都用于指示程序要引用的名字空间。在声明引用名字空都用于指示程序要引用的名字空间。在声明引用名字空 间的某个成员之前,成员必须已经在名字空间中进行了间的某个成员之前,成员必须已经在名字空间中进行了 声明或进行了定义。声明或
23、进行了定义。 示例示例 #include namespace NS1 /初始定义名字空间初始定义名字空间NS1 extern int x; /说明整型变量说明整型变量x void fun(int); /说明函数说明函数fun(int) void fun(long) /定义函数定义函数fun(long) coutProcessing a long argument endl; namespace NS1 /扩展定义名字空间扩展定义名字空间NS1 int x=5; /定义整形变量定义整形变量x void fun(int) /定义函数定义函数fun(int) coutProcessing a int
24、 argumentendl; void main() int y=20; using NS1:x; /说明引用变量说明引用变量x using:NS1:fun; /说明引用函数说明引用函数fun() x=10; fun(4); fun(4L); coutx=xendl; couty=yendl; 1、访问名字空间的成员、访问名字空间的成员 访问名字空间的成员有访问名字空间的成员有4种方式:种方式: (1)直接访问成员)直接访问成员 格式如下:格式如下: 名字空间名字名字空间名字:成员名字成员名字 因此,直接访问总能惟一地访问指定名字空间的成员。因此,直接访问总能惟一地访问指定名字空间的成员。 (
25、2)指定名字空间(使用)指定名字空间(使用using namespace 语句)语句) 指定名字空间的格式如下:指定名字空间的格式如下: using namespace 名字空间;名字空间; /直接使用成员名字直接使用成员名字 (3)声明引用成员(使用)声明引用成员(使用using语句)语句) 声明引用成员的格式如下:声明引用成员的格式如下: using 名字空间名字空间:名字名字 /直接使用成员名字直接使用成员名字 (4)使用别名法)使用别名法 声明引用成员的格式如下:声明引用成员的格式如下: namespace 别名别名=名字空间;名字空间; /使用使用“别名别名:成员名字成员名字” 本方
26、法与直接方法成员方法类似,只是加了一个别名。例如有以下两本方法与直接方法成员方法类似,只是加了一个别名。例如有以下两 个名字空间个名字空间NSA和和NSB,分别声明了同名的类模板:,分别声明了同名的类模板: namespace NSA template class Array private: T *ia; int ssize; ; 以上的类以上的类Array被封装在名字空间被封装在名字空间NSA中,在使该类前,中,在使该类前, 必须使必须使NSA名字空间可见。名字空间可见。 namespace NSB template class Array private: T *ia; int ssiz
27、e; ; 以上的类以上的类Array被封装在名字空间被封装在名字空间NSB中,在使该类前,必须使中,在使该类前,必须使NSB 名字空间可见。因为使用了名字空间,两个名字空间可见。因为使用了名字空间,两个Array类分别在不同的名类分别在不同的名 字空间中,所以不会存在冲突。其中四种使用方式如下:字空间中,所以不会存在冲突。其中四种使用方式如下: 第一种用法:直接用法。第一种用法:直接用法。 NSA:Array a; NSB:Array b; 第二种用法:指定名字空间。第二种用法:指定名字空间。 using namespace NSA; Array a; using namespace NSB;
28、 Array b; 第三种用法:声明引用成员。第三种用法:声明引用成员。 using NSA:Array; Array a; using NSB:Array; /错误,存在同名的成员错误,存在同名的成员 Array b; 值得注意的是,上述语句是错误的,应将两个类模板改为不同的名字值得注意的是,上述语句是错误的,应将两个类模板改为不同的名字 ,如将,如将NSB中的中的Array改为改为Array1,则以下语句是正确的:则以下语句是正确的: using NSA:Array; Array a; using NSB:Array1; Array b; 第四种用法:使用别名法。第四种用法:使用别名法。
29、namespace us=NSA; namespace ms=NSB; us:Array a; ms:Array b; 示例:示例: #include namespace NS1 int x=10; namespace NS2 int x=20; void main() using NS1:x; coutx=xendl; using NS2:x; coutx=xendl; 2、使用作用域运算符、使用作用域运算符“:”访问成员访问成员 当名字空间的成员和程序的全局标识符同名时,可以通当名字空间的成员和程序的全局标识符同名时,可以通 过作用域运算符过作用域运算符“:”既定程序的全局标识符;当名字空
30、既定程序的全局标识符;当名字空 间的成员和程序的标识符同名时,首先访问的是程序的间的成员和程序的标识符同名时,首先访问的是程序的 局部标识符。局部标识符。 示例:示例: #include int x=20; /全局变量全局变量 namespace NS1 int x=10; void main() using namespace NS1; coutx=:xendl; 3、名字空间的嵌套、名字空间的嵌套 名字空间也可以像类那样嵌套,形成多个层次的作用域名字空间也可以像类那样嵌套,形成多个层次的作用域 ,因此,在访问名字空间的成员时,就有可能使用多个,因此,在访问名字空间的成员时,就有可能使用多个
31、 域运算符。域运算符。 示例:示例: #include namespace NS1 /NS1的初始定义的初始定义 int x=10; void fun1() coutNS1s fun1()endl; namespace NS2 int y=20; void fun2() coutNS2s fun2()endl; using NS1:fun1; /using说明,全局名字空间限定说明,全局名字空间限定fun1 using NS1:x; /using说明,全局名字空间限定说明,全局名字空间限定x using NS1:NS2:fun2; /using说明,多重名字空间限定说明,多重名字空间限定fun2 using NS1:NS2:y; /using说明,多重名字空间限定说明,多重名字空间限定y void main() fun1(); fun2(); coutx=xendl; couty=yendl; 4、 std名字空间名字空间 本章前面的程序都是使用标准本章前面的程序都是使用标准C+编写的,其头文件都编写的,其头文件都 带有带有.h扩展名,而扩展名,而ANSI/ISO标准标准C+头文件不带扩展头文件不带扩展 名。这是因为名。这是因为C+是从是从C发展而来,某些头文件,如都发展而来,某些头文件,如都 是从是从C中沿袭过来的,
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年大学大一(建筑学)建筑制图基础综合测试题及答案
- 护理部护理实践技能评估
- 2025年前台电子练习卷
- 护理质量改进的领导力
- 临床医学教材课件内科学第八篇风湿性疾病第六章抗磷脂综合征
- 小学语文部编版习作教学策略应用于案例分析
- 2026六年级数学上册 分数除法学习策略
- 2026六年级数学上册 百分数计算技巧
- 2026年医疗废物规范化管理督导工作计划
- 消防安全隐患排查整治方案
- 2025年税务局上海面试题及答案
- 二方审核管理办法
- 北京政务云管理办法
- 学堂在线 雨课堂 学堂云 工程伦理2.0 章节测试答案
- 道法人须有自尊课件-+2024-2025学年统编版道德与法治七年级下册
- 2.3地域文化与城乡景观 课件
- T/CIE 115-2021电子元器件失效机理、模式及影响分析(FMMEA)通用方法和程序
- 国土空间规划概述
- GB 5768.1-2025道路交通标志和标线第1部分:总则
- 《水遇冷以后》说课(附反思板书)(课件)四年级下册科学苏教版
- 园长陪餐管理制度
评论
0/150
提交评论