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;有七座桥将普雷格尔河中两个岛及岛与河岸连接起来。 能否走过这样的七座桥&#xff0c;并且每桥只走一次&#xff1f;瑞士数学家欧拉最终解决了这个问题并由此创立了拓扑学。欧拉通过对七桥问题的研究&#xff0c;不仅圆满地回答…

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

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

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

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

CRT

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

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

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

java多线程笔记补充之 线程控制操作

线程休眠:让执行的线程暂停一段时间&#xff0c;进入计时等待状态。 方法:staticvoid sleep(long millis) 调用sleep后&#xff0c;当前线程放弃CPU,在指定时间段之内&#xff0c;sleep所在线程不会获得执行的机会。 此状态下的线程不会释放同步锁/同步监听器. 该方法更多的用…

java5新特性静态引用、foreach、自动装箱和泛型枚举以及可变参数的总结

静态引用 导入(import)表示去找哪一个类&#xff0c;去哪一个包下去找哪些被使用到的类。 在java中有一个语言核心包&#xff1a;java.lang. 使用java.lang包中的API&#xff0c;不需要引用&#xff0c;直接能找到&#xff0c;但是&#xff0c;如果我们使用到的API不呼吁java.l…

java8新特性lambda表达式、函数式编程、方法引用和接口默认方法以及内部类访问外部变量

一提到java是一种什么语言&#xff1f; 大多数人肯定异口同声的说是一门面向对象的语言&#xff0c;这种观点从我们开始学java就已经根深蒂固了&#xff0c;但是学到java8新特性函数式编程的时候&#xff0c;我才知道java并不是纯面向对象的语言。 lambda表达式的详细教程 lam…

javaWeb回忆思维导图

出处&#xff1a;https://blog.csdn.net/jackfrued/article/details/42617675 https://www.cnblogs.com/xieyupeng/p/6961667.html

Spring详细导包截图以及IOC和DI思想

思想 IOC DI Spring中的工厂(容器) ApplicationContext&#xff1a; BeanFactory(过时)&#xff1a; BeanFactory和ApplicationContext区别 BeanFactory&#xff1a; 1.Spring原始接口&#xff0c;针对原始接口实现类功能较为单一 2.是在getBean的时候才会生成类的实例…

毕业两年的我--奋斗中的程序员

又到一年毕业季&#xff0c;不知不觉&#xff0c;自己毕业快两年了&#xff0c;在这两年中&#xff0c;从一位小白程序员蜕化到现在的拥有两年经验的C程序员&#xff0c;这两年里面&#xff0c;不敢说成长有多快&#xff0c;进步有多大&#xff0c;但是感觉很踏实&#xff0c;每…

spring配置讲解

Bean元素 Bean元素进阶 scope属性&#xff1a; 1.singleton(默认值):单例对象.被标识为单例的对象在spring容器中只会存在一个实例 2.prototype:多例原型.被标识为多例的对象,每次再获得才会创建.每次创建都是新的对象.整合struts2时,ActionBean必须配置为多例的. 3.request…

情商低的七种表现,你占了几个

你身边有没有这样的人&#xff1a;大家刚刚还聊的热火朝天&#xff0c;却在他进门的瞬间&#xff0c;整场“冷冻结冰”&#xff0c;大家都各忙各的&#xff0c;避免与他交流。我们称这样的人为“冷场帝”。那么&#xff0c;“冷场帝”是如何养成的&#xff1f;这样的人通常情商…

spring属性注入

注入方式 set方法注入 构造函数注入 p名称空间注入 spel注入(#表示理解为引用) 练习代码&#xff1a; <!-- 第二天 set注入 index:索引 ref:引用对象 type:参数类型--><bean name"person" class"com.spring.bean.Person"><constructor-a…

你所不知道的C和C++运行库

转自&#xff1a;http://blog.csdn.net/ithzhang/article/details/20160009 你所不知道的C和C运行库    周五晚&#xff0c;小雨&#xff0c;少见的未加班。无聊&#xff0c;遂准备写一篇博客&#xff0c;介绍一下C和C运行库&#xff0c;只因发现工作几年的人对此一知半解的…

使用注解配置spring如@Compnent、@Service、@Consroller、@scope和@value的使用

步骤 1.导包42spring-aop如图&#xff1a;为学习到该阶段需要用到的包(里面的aoptest是spring和junit整合测试的时候用到的)2.为主配置文件引入新的命名空间(约束)3.开启使用注解代理配置文件<?xml version"1.0" encoding"UTF-8"?> <beans xmln…

java实现深度优先搜索 (DFS) 算法

度优先搜索&#xff08;Depth First Search&#xff0c;DFS&#xff09;算法是一种用于遍历或搜索图或树的算法。这种算法从一个节点开始&#xff0c;沿着一条路径尽可能深地搜索&#xff0c;直到遇到不能继续前进的节点时返回上一个节点&#xff0c;然后继续搜索其他路径。具体…

spring整合JDBC

文章目录spring提供了很多模板整合Dao技术spring中提供了一个可以操作数据库的对象.对象封装了jdbc技术.如何用Spring中的jdbc模板对数据库操作&#xff1a;spring配置进阶内容JDBCDaoSupport的使用spring提供了很多模板整合Dao技术 因为在jdbc、Hibernate、Mybatis中都有对数据…