程序异常处理

上传人:豆浆 文档编号:5903184 上传时间:2017-09-08 格式:DOC 页数:24 大小:121.50KB
返回 下载 相关 举报
程序异常处理_第1页
第1页 / 共24页
程序异常处理_第2页
第2页 / 共24页
程序异常处理_第3页
第3页 / 共24页
程序异常处理_第4页
第4页 / 共24页
程序异常处理_第5页
第5页 / 共24页
点击查看更多>>
资源描述

《程序异常处理》由会员分享,可在线阅读,更多相关《程序异常处理(24页珍藏版)》请在金锄头文库上搜索。

1、C+之异常处理一个好的程序应该能对多种不同的特殊情况,做出不同的反应,对于突发情况也应有对应的处理方法。我们在编程时应考虑到各种突发情况,并在程序中给出解决方案,使程序的健壮性增强。假设有一个司机从 A 地开车前往 B 地。若在某处有一岔路口,一般选择左边,路程会近一些。但当司机选择左边,将车开到途中时发现正在修路(突发情况),无法通过。这时,司机就会掉头回到刚才的岔路口处,重新选择右边的路,继续前进。我们所编的程序也应该像这样,有一定的智能化的设计。这就要求在编写程序时,应该试着确定程序可能出现的错运,然后加入处理错误的代码。例如:当程序执行文件 I0 操作时,应测试文件打开以及读写操作是否

2、成功,并且在出现错误时做出正确的反应。随着程序复杂性的增加,为处理错误而必须包括在程序中代码的复杂性也相应地增加了。为使程序更易于测试和处理错误,C+实现了异常处理机制。一、异常概念1异常的概念程序的错误,一种是编译错误,即语法错误。如果使用了错误的语法、函数、结构和类,程序就无法被生成运行代码。另一种是在运行时发生的错误,它分为不可预料的逻辑错误和可以预料的运行异常。运行异常,可以预料,但不能避免,它是由系统运行环境造成的。如,内存空间不足,而程序运行中提出内存分配申请时,得不到满足,就会发生异常:#include/void f(char *str)ifstream source(str);

3、 打开 str 串中的文件if(sourcefail()打不开cerr #include #include void main(int argc,char *argv) ifstream source(argv1); /打开文件 char line128;try if(source.fail() /如果打开失败throw argv1;catch (char *s) cout提示符后输入命令 ch10_1 abc.txt屏幕显示结果为: error opening the file abc.txt若输入命令 ch10_1 xyz.txt 则屏幕显示结果为: How are you? Fine!例

4、题 2:一个除零异常:#includedouble Div(double,double);void main()try cout #include using namespace std; enum SUCCESS, FAILURE; class File public: File (const char *) public: bool IsValid() const return false; public: int OpenNew() const return FAILURE; ; class Exception /*.*/; /general base class for excepti

5、ons class FileException: public Exception public: FileException(const char *p) : s(p) public: const char * Error() const return s.c_str(); private: string s; ; void func(File& ); int main() try /outer try File f (db.dat); func(f); / 1 catch(.) / 7 /this handler will catch the re-thrown exception; /n

6、ote: the same exception type is required cout中 当一个函数提出的异常没有包括在这个函数的异常规范中时,程序会自动调用函数unexpected()来处理这个异常。函数 unexpected()的缺省行为是调用使用者通过set_unexpected()函数注册的函数。假如没有任何函数通过 set_unexcepted()来注册,函数unexpected()则调用函数 terminate()。这三个函数的原型如下。 void unexpected(); typedef void (*unexpected_handler)(); unexpected_ha

7、ndler set_unexpected(unexpected_handler) throw(); void terminate(); 函数 set_unexpected()的返回值是前一次通过 set_unexpected()注册的函数指针。 函数 terminate()可以通过 unexpected()来调用,或者当找不到一个异常句柄时程序自动调用。terminate()函数的缺省行为是调用函数 abort()。这个缺省函数即刻中止程序运行。你可以改变当一个异常没有出现于函数的异常规范中时的程序中止方式。如果你不想你的程序通过调用 abort()来中止,你可以定义另外一个函数来替代它。这样

8、的函数通过 set_terminate()函数来注册并由 terminate()调用。函数 set_terminate()的定义如下 typedef void (*terminate_handler)(); terminate_handler set_terminate(terminate_handler) throw(); 这个函数的返回值是前一次通过函数 set_terminate()来注册的函数指针。 头文件定义了处理异常的函数,类及其数据成员和成员函数。 十、 具有异常规范的虚拟函数 一个虚拟函数也可以定义异常规范。但是,一个子类中的虚拟函数提出的异常不能比父类中的虚拟函数提出的异常多

9、。也就是说,一个子类中的虚拟函数规范不能比父类中的虚拟函数规范更宽松。而一个子类中的虚拟函数提出的异常比父类中的虚拟函数提出的异常少则是允许的。例如 class CoWindow public: virtual void show() throw(int); virtual void getFocus() throw(int, char); ; class CoDialogBox:public CoWindow public: virtual void show() throw(int, char); /错误,异常规范较宽松 virtual void getFocus() throw(int)

10、; /可以,异常规范更严历 ; 编译器针对 CoDialog:show()会给出编译错误,因为在运行时这个函数既可以提出 int 类型异常也可以提出 char 类型异常。而在父类定义中,这个虚拟函数只能提出 int 类型异常。另一方面,CoDialog:getFocus()是允许的,因为它的规范比父类中的虚拟函数的异常规范要求更严历。 例题:下面我们用示例演示一下异常处理:1 #include stdafx.h2 #include 3 template 5 T Div(T x,T y) if(y=0) throw y;/抛出异常 return x/y; int main() int x=5,y

11、=0;double x1=5.5,y1=0.0;try /被检查的语句 std:cout template T Div(T x,T y) if(y=0)throw y;/抛出异常return x/y;int main() int x=5,y=1;double x1=5.5,y1=0.0;try std:cout using namespace std; class Exit; /used as exception object int main() int num; coutnum; if (num = 99) throw Exit(); /exit the loop cout头文件中定义)派

12、生。这一层次使得应用程序能够在单一的 catch 语句中捕获这些异常: catch (std:exception& exc) / handle exception of type std:exception as well as /any exception derived from it 那些通过语言内建操作符抛出的标准异常是: std:bad_alloc /by operator new std:bad_cast /by operator dynamic_cast std:bad_typeid /by operator typeid std:bad_exception /thrown wh

13、en an exception specification of 所有的标准异常都提供了成员函数 what(),它返回一个用来描述异常细节的字符串。注意,标准库还有另外一个被它的组件抛出的的异常集合。 异常处理层次 异常在一个自下向上的层次中捕获:派生层次越深的异常越先被处理,例如: #include #include using namespace std; int main() try char * buff = new char100000000; /.use buff catch(bad_alloc& alloc_failure) / bad_alloc is /derived fro

14、m exception coutmemory allocation failure; /. handle exception thrown by operator new catch(exception& std_ex) cout std_ex.what() endl; catch(.) / exceptions that are not handled elsewhere are caught here coutunrecognized exceptionendl; return 0; 派生层次越深的 handler 必须出现在其基类的前面。这是因为 handler 的匹配过程是按照出现的顺

15、序进行的。因此有可能某个 handler 永远不会被执行,例如,把一个处理派生类异常的 handler 放在处理基类异常的 handler 的后面。例如: catch(std:exception& std_ex) /bad_alloc exception is always handled here /.handle the exception catch(std:bad_alloc& alloc_failure) /unreachable coutmemory allocation failure; C中的其它错误处理方法 以上,我们讨论了 C中的异常处理。 C同时提供了一些其它错误处理方法。这里略述如下。 (1) 使用 assert()来测试编程和设计错误。如果测试结果为非,程序中止运行。为了保证程序能够运行,程序源代码中的错误必须纠正。这在程序调试时非常有用。 (2) 简单忽略错误。这一方法对个人开发的私用程序是可以的。但是对一个面向市场、大众的软件产品却是致命的。 (3) 中止程序运行。此方法中断程序运行,防止错误结果产生。实际上这种方法对某些类型错误,特别是非致命性的(nonf

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 行业资料 > 其它行业文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号