C++异常处理类与自定义异常处理类

转自:http://blog.csdn.net/makenothing/article/details/43273137


例1:自定义一个继承自excepton的异常类myException

C++标准中,定义在<stdexcept>中的任何异常类都派生自exception Class,本例也只是简单地由exception继承,在try段抛出一个异常并捕捉。代码如下:

[cpp] view plaincopy
print?在CODE上查看代码片派生到我的代码片
  1. /*++ test.cpp  
  2. version:1.0  
  3. decript:define a exception class named myException  
  4.         derived from base class exception  
  5.         which is declared in <exception>  
  6. created:2011-08-14  
  7. author: btwsmile  
  8. --*/    
  9. #include<exception>    
  10. #include<iostream>    
  11. using namespace std;    
  12.     
  13. //customized exception class 'myException'    
  14. class myException:public exception    
  15. {    
  16. public:    
  17.     myException():exception("ERROR! Don't divide a number by integer zero.\n")    
  18.     {    
  19.     }    
  20. };    
  21. //entry of the application    
  22. int main()    
  23. {    
  24.     int x=100,y=0;    
  25.     try    
  26.     {    
  27.         if(y==0) throw myException();    
  28.         else cout<<x/y;    
  29.     }    
  30.     catch(myException& me)    
  31.     {    
  32.         cout<<me.what();    
  33.     }    
  34.     system("pause");    
  35.     return 0;    
  36. }    


结果如下:
ERROR! Don't divide a number by integer zero.
请按任意键继续. . .                                                  

显然,异常被捕捉到了。此处需要说明的是,VC对异常处理类exception进行了扩展,本例之所以能够使用exception("ERROR!....")的初始化方法正出于这样的原因,C++标准是不允许这样做的。

与此同时,VC又没有遵循标准,有力地支持terminate和unexpected,它只保留了语法,却在编译运行时不提供支持。为了结合terminate和unexpected更加深入了解C++的异常处理,下面的例子采用Dev cpp IDE实现。

例2:依照C++标准实现自定义异常类myException并将throw语句封装到函数check()中

涉及到的更改正如标题所述,(1)重写基类的what()函数,返回错误信息;(2)将throw myException()封装到check()函数中;(3)允许check()函数抛出myException类型的异常。代码如下:

[cpp] view plaincopy
print?在CODE上查看代码片派生到我的代码片
  1. /*++ test.cpp  
  2. version:1.1  
  3. decript:define a exception class named myException   
  4.         according to C++ standard,  
  5.         derived from base class exception  
  6.         which is declared in <exception>  
  7.         !also,encapusulate throw into a function  
  8. created:2011-08-14  
  9. author: btwsmile  
  10. --*/    
  11. #include<exception>    
  12. #include<iostream>    
  13. using namespace std;    
  14.     
  15. //customized exception class 'myException'    
  16. class myException:public exception    
  17. {    
  18. public:    
  19.    const char* what()const throw()//#1     
  20.    {    
  21.         return "ERROR! Don't divide a number by integer zero.\n";    
  22.    }        
  23. };    
  24. void check(int y) throw(myException)//#2    
  25. {    
  26.      if(y==0) throw myException();    
  27. }    
  28. //entry of the application    
  29. int main()    
  30. {    
  31.     int x=100,y=0;    
  32.     try    
  33.     {    
  34.         check(y);    
  35.         cout<<x/y;    
  36.     }    
  37.     catch(myException& me)    
  38.     {    
  39.         cout<<me.what();    
  40.     }    
  41.     system("pause");    
  42.     return 0;    
  43. }    


结果与例1完全相同。需说明的是,紧跟check()后的throw列表表明允许该函数抛出的异常类型。这里不得不产生疑问,如果抛出了一个不被允许的异常类型将怎样?

例3:抛出unexpected异常

check函数体之后的throw列表,规定了允许抛出的异常类型,一旦违背,就将触发unexpected。可以把unexpected看作系统自动调用的CALLBACK函数,不同的是,也可以手工触发它的执行。本例的情况属于前者。代码如下:

[cpp] view plaincopy
print?在CODE上查看代码片派生到我的代码片
  1. /*++ test.cpp  
  2. version:1.3  
  3. decript:define an unexpected excption handler,  
  4.         set it by using set_unexpected,  
  5.         modify the throw list of function check  
  6. created:2011-08-14  
  7. author: btwsmile  
  8. --*/    
  9. #include<exception>    
  10. #include<iostream>    
  11. using namespace std;    
  12.     
  13. //customized exception class 'myException'    
  14. class myException:public exception    
  15. {    
  16. public:    
  17.    const char* what()const throw()    
  18.    {    
  19.         return "ERROR! Don't divide a number by integer zero.\n";    
  20.    }        
  21. };    
  22. void check(int y) throw()//#1 only int-type exception is permitted    
  23. {    
  24.      if(y==0) throw myException();    
  25. }    
  26. void myUnexpected()    
  27. {    
  28.      cout<<"Unexpected exception caught!\n";    
  29.      system("pause");    
  30.      exit(-1);    
  31. }    
  32. //entry of the application    
  33. int main()    
  34. {    
  35.     unexpected_handler oldHandler=set_unexpected(myUnexpected);    
  36.     int x=100,y=0;    
  37.     try    
  38.     {    
  39.         check(y);    
  40.         cout<<x/y;    
  41.     }    
  42.     catch(myException& me)    
  43.     {    
  44.         cout<<me.what();    
  45.     }    
  46.     system("pause");    
  47.     return 0;    
  48. }    

结果如下:

Unexpected exception caught!
请按任意键继续. . .                    

check函数的throw列表为空,即不允许抛出任何类型的异常,然而实际上当异常发生时,系统不能等闲视之,它将调用unexpected处理方法。所以,限定一个函数throw列表为空是值得程序员警醒的事,需要特别留意。如果将#1处的代码修改为throw(int)等也能得到相同的结果。所谓unexpected异常,说白了就是函数体允许抛出异常类型范围之外的异常。如果check函数后面根本没有throw,则表示函数任何类型的异常都被允许。

例4:抛出函数体允许的异常,但没被捕捉到的情况

思考这样一个问题,如果函数check的throw列表中有异常类型myException,而且在y==0时,它的确抛出myException类型的异常,但是没有被catch到,这时会发生什么?

在正式回答这个问题之前,先讨论“没被catch到”的意思。比如,修改例3的代码如下:(##为修改之处)

[cpp] view plaincopy
print?在CODE上查看代码片派生到我的代码片
  1. /*++ test.cpp  
  2. version:1.4.1  
  3. decript:  
  4.         how to understand "exception not caucht"?  
  5. created:2011-08-14  
  6. author: btwsmile  
  7. --*/    
  8. #include<exception>    
  9. #include<iostream>    
  10. using namespace std;    
  11.     
  12. //customized exception class 'myException'    
  13. class myException:public exception    
  14. {    
  15. public:    
  16.    const char* what()const throw()    
  17.    {    
  18.         return "ERROR! Don't divide a number by integer zero.\n";    
  19.    }        
  20. };    
  21. void check(int y) //any type of exception is permitted    
  22. {    
  23.      if(y==0) throw myException();    
  24. }    
  25. void myUnexpected()    
  26. {    
  27.      cout<<"Unexpected exception caught!\n";    
  28.      system("pause");    
  29.      exit(-1);    
  30. }    
  31. //entry of the application    
  32. int main()    
  33. {    
  34.     unexpected_handler oldHandler=set_unexpected(myUnexpected);    
  35.     int x=100,y=0;    
  36.     try    
  37.     {    
  38.         check(y);    
  39.         cout<<x/y;    
  40.     }    
  41.     catch(int &e) //##1 no catch sentence matches the throw type    
  42.     {    
  43.         cout<<e<<endl;    
  44.     }    
  45.     /*               ##2 if add this part, any type which's not handler before will  
  46.                         be caught  
  47.     catch(...)  
  48.     {  
  49.                     cout<<"Unkown exception caught!\n";  
  50.          }  
  51.     */    
  52.     system("pause");    
  53.     return 0;    
  54. }    


编译运行,程序将会出错,因为check函数抛出的myException异常没有被处理。在缺省情况下,一旦出现抛出异常没被处理的问题,系统将自动调用abort()函数,终止程序允许,在控制台将会看到这样的提示:
This application has requested the Runtime to terminate it in an unusual way.Please contact the application's support team for more information.

不过可以增加##2部分的代码,catch(...)表示捕捉任何类型的异常。

注意:check函数不被允许的异常类型并不会进入到catch语句的判断中来,因此catch(...)对unexpected exception没有作用。

仍然考虑没有##2部分的情况。正如前面所述,系统将自动调用abort()函数终止程序。实际上,它触发的是terminate,类似于unexpected,仍然可以自定义terminate的处理方法。甚至terminate语法上跟unexpected都十分近似。修改代码为:

[cpp] view plaincopy
print?在CODE上查看代码片派生到我的代码片
  1. /*++ test.cpp  
  2. version:1.4.2  
  3. decript:  
  4.         how to understand "exception not caucht"?  
  5. created:2011-08-14  
  6. author: btwsmile  
  7. --*/    
  8. #include<exception>    
  9. #include<iostream>    
  10. using namespace std;    
  11.     
  12. //customized exception class 'myException'    
  13. class myException:public exception    
  14. {    
  15. public:    
  16.    const char* what()const throw()    
  17.    {    
  18.         return "ERROR! Don't divide a number by integer zero.\n";    
  19.    }        
  20. };    
  21. void check(int y) //any type of exception is permitted    
  22. {    
  23.      if(y==0) throw myException();    
  24. }    
  25. void myUnexpected()    
  26. {    
  27.      cout<<"Unexpected exception caught!\n";    
  28.      system("pause");    
  29.      exit(-1);    
  30. }    
  31. void myTerminate() //##1 set it be the terminate handler    
  32. {    
  33.      cout<<"Unhandler exception!\n";    
  34.      system("pause");    
  35.      exit(-1);    
  36. }    
  37. //entry of the application    
  38. int main()    
  39. {    
  40.     unexpected_handler oldHandler=set_unexpected(myUnexpected);    
  41.     terminate_handler preHandler=set_terminate(myTerminate);    
  42.     int x=100,y=0;    
  43.     try    
  44.     {    
  45.         check(y);    
  46.         cout<<x/y;    
  47.     }    
  48.     catch(int &e) //no catch sentence matches the throw type    
  49.     {    
  50.         cout<<e<<endl;    
  51.     }    
  52.     system("pause");    
  53.     return 0;    
  54. }    

结果如下:

Unhandler exception!
请按任意键继续. . .    

结论:C++为异常处理提供了友好的支持。

用户可以自定义异常类型,异常类型并不受到限制,可以是内建数据类型如int,double等,也可以是自定义的类,也可以从C++某个异常类继承下来。例1采用了派生自exception的方法。

除此之外,在定义函数时,可以显式指定函数体抛出的异常类型。隐式情况下,缺省允许函数抛出任何类型的异常。有可以增加throw语句,对异常类型加以限制。特别的是,throw()表示不允许函数抛出任何类型的异常。如果违反了throw列表规定的异常类型,系统将调用unexpected hanlder进行处理,可以自定义unexpected异常处理方法。例2和例3对它们进行了说明。

如果对于函数体throw列表合法的异常被抛出,但是却没有被程序捕捉处理,系统将调用terminate handler进行处理。缺省情况下,只是简单调用abort()函数终止程序,同样可以自定义terminate处理方法。例4对它进行了说明。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/509460.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络编程概念总结

计算机网路: 计算机网络&#xff0c;是指将地理位置不同的具有独立功能的多台计算机及其外部设备&#xff0c;通过通信线路连接起来&#xff0c;在网络操作系统&#xff0c;网络管理软件及网络通信协议的管理和协调下&#xff0c;实现资源共享和信息传递的计算机系统。 从逻辑…

数据结构实验:连通分量个数

题目描述 在无向图中&#xff0c;如果从顶点vi到顶点vj有路径&#xff0c;则称vi和vj连通。如果图中任意两个顶点之间都连通&#xff0c;则称该图为连通图&#xff0c; 否则&#xff0c;称该图为非连通图&#xff0c;则其中的极大连通子图称为连通分量&#xff0c;这里所谓的极…

如何优化简历

http://mp.weixin.qq.com/s?__bizMzAxMzUzNzYyNA&mid402350492&idx1&sn0e180c05248c845d6ed3e43f5006679e#rd

网络编程之 application/x-www-form-urlencoded MIME编码

编码作用&#xff1a; https://baike.baidu.com/item/魏杰/15581?fraladdin如果我们想要这种表单提交中链接的中文信息不显示出来&#xff0c;那么我们就需要通过MIME编码把中文转换成另外一种编码显示出来,但是这种编码在国内的浏览器中运用的并不多&#xff0c;谷歌浏览器用…

数据结构实验之图论八:欧拉回路

题目描述 在哥尼斯堡的一个公园里&#xff0c;有七座桥将普雷格尔河中两个岛及岛与河岸连接起来。 能否走过这样的七座桥&#xff0c;并且每桥只走一次&#xff1f;瑞士数学家欧拉最终解决了这个问题并由此创立了拓扑学。欧拉通过对七桥问题的研究&#xff0c;不仅圆满地回答…

Linux面试相关

1.TCP/IP 建立连接的过程&#xff1f;&#xff08;3-way shake&#xff09; Client与server建立TCP连接时&#xff1a;首先Client向server发SYN&#xff08;请求&#xff09;&#xff0c;然后server回复&#xff08;应答请求&#xff09;&#xff0c;最后Client回复&#xff0c…

网络编程之 传输层的协议TCP与UDP

传输层协议: TCP和UDP的区别: TCP&#xff1a;面向连接(经历三次握手)、传输可靠(保证数据正确性,保证数据顺序)、用于传输大量数据(流模式)、速度慢&#xff0c;建立连接需要开销较多(时间&#xff0c;系统资源)。 服务端和客户端 UDP&#xff1a;面向非连接、传输不可靠(丢…

n a^o7 !

题目描述 All brave and intelligent fighters, next you will step into a distinctive battleground which is full of sweet and happiness. If you want to win the battle, you must do warm-up according to my instructions, which can make you in the best state prep…

socket阻塞与非阻塞,同步与异步

转自&#xff1a;http://blog.csdn.net/hguisu/article/details/7453390 socket阻塞与非阻塞&#xff0c;同步与异步 作者&#xff1a;huangguisu 1. 概念理解 在进行网络编程时&#xff0c;我们常常见到同步(Sync)/异步(Async)&#xff0c;阻塞(Block)/非阻塞(Unblock)四种调…

网络编程之如何通过URL获取网页代码

java.net 类 URL java.lang.Objectjava.net.URL所有已实现的接口&#xff1a; Serializable public final class URLextends Objectimplements Serializable类 URL 代表一个统一资源定位符&#xff0c;它是指向互联网“资源”的指针。资源可以是简单的文件或目录&#xff0c;…

数据结构实验之图论七:驴友计划

题目描述 做为一个资深驴友&#xff0c;小新有一张珍藏的自驾游线路图&#xff0c;图上详细的标注了全国各个城市之间的高速公路距离和公路收费情况&#xff0c;现在请你编写一个程序&#xff0c;找出一条出发地到目的地之间的最短路径&#xff0c;如果有多条路径最短&#xff…

Windows完成端口(IOCP)

http://blog.csdn.net/piggyxp/article/details/6922277

图结构练习——最小生成树

题目描述 有n个城市&#xff0c;其中有些城市之间可以修建公路&#xff0c;修建不同的公路费用是不同的。现在我们想知道&#xff0c;最少花多少钱修公路可以将所有的城市连在一起&#xff0c;使在任意一城市出发&#xff0c;可以到达其他任意的城市。 输入 输入包含多组数据&a…

Windows 中_T和L

_T("")是一个宏&#xff0c;定义于tchar.h下。[1]&#xfeff; #define _T(x) _ _T(x)   #ifdef _UNICODE #define _ _T(x) L ## x #else /* ndef _UNICODE */ #define _ _T(x) x 他的作用是让你的程序支持Unicode编码 因为Windows使用两种字符集ANSI和UN…

多线程笔记补充之线程通信wait和notify方法以及Lock和Condition接口的使用

线程通信-wait和notify方法介绍: java.lang.Object类提供类两类用于操作线程通信的方法. wait():执行该方法的线程对象释放同步锁,JVM把该线程存放到等待池中,等待其他的线程唤醒该线程. notify:执行该方法的线程唤醒在等待池中等待的任意一个线程,把线程转到锁池中等待. notif…

数据结构实验之图论六:村村通公路

题目描述 当前农村公路建设正如火如荼的展开&#xff0c;某乡镇政府决定实现村村通公路&#xff0c;工程师现有各个村落之间的原始道路统计数据表&#xff0c;表中列出了各村之间可以建设公路的若干条道路的成本&#xff0c;你的任务是根据给出的数据表&#xff0c;求使得每个村…

技术人生“白天求生存,晚上谋发展”

白天求生存&#xff0c;晚上谋发展 这句话最近在团队经常有人说&#xff0c;其实我也深有体会&#xff0c;因为我看到的技术牛人他们背后肯定有一段很长时间的艰苦时光&#xff0c;可能是3年&#xff0c;也可能是8年&#xff0c;也可能一直还在坚持。 其实我们周围大部份人有一…

CRT

当C Runtime函数库于20世纪70年代产生出来时&#xff0c;PC的内存容量还很小,多任务是个新奇观念&#xff0c;更别提什么多线程了。因此以当时产品为基础所演化的C Runtime函数库在多线程&#xff08;multithreaded&#xff09;的表现上有严重问题&#xff0c;无法被多线程程序…

java多线程笔记补充之线程的生命周期

多线程通信的时候很容易造成死锁,死锁无法解决,只能避免: 当A线程等待由B线程持有的锁,而B线程正在等待A线程持有的锁时,发生死锁现象,JVM不检测也不试图避免这种情况,所以程序员必须保证不导致死锁. 避免死锁法则: 当多个线程都要访问共享的资源A,B,C时,保证每一个线程都按照…