自定义C++异常处理

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

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

  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类型的异常。代码如下:

  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函数,不同的是,也可以手工触发它的执行。本例的情况属于前者。代码如下:

 

  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的代码如下:(##为修改之处)

  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都十分近似。修改代码为:

  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/352970.shtml

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

相关文章

DCL并非单例模式专用

我相信大家都很熟悉DCL&#xff0c;对于缺少实践经验的程序开发人员来说&#xff0c;DCL的学习基本限制在单例模式&#xff0c;但我发现在高并发场景中会经常遇到需要用到DCL的场景&#xff0c;但并非用做单例模式&#xff0c;其实DCL的核心思想和CopyOnWrite很相似&#xff0c…

使用CLI扩展和重新平衡Couchbase集群

Couchbase通过多种方式提供高可用性和灾难恢复 &#xff1a; 同质簇 复写 集群内复制 备份还原 机架区意识 该博客将展示如何使用Couchbase命令行界面&#xff08;CLI&#xff09;创建Couchbase集群。 此外&#xff0c;还可以使用Couchbase REST API和Couchbase Web Consol…

将php源码修改成存在注入的源码,天融信关于ucms系统存在代码注入漏洞的分析...

一、背景介绍UCMS是一款简单的开源内容管理系统&#xff0c;可以非常方便的通过它来快速开发各种各种企业站、文章站、站群系统。系统兼容PHP5.2–PHP7.0&#xff0c;在APACHE、NGINX、IIS上都能使用&#xff0c;支持MySQL SQLite两种数据库。后台简洁高效&#xff0c;上手容易…

第1章 计算机系统漫游(深入理解计算机系统)

1 #include <stdio.h> 2 3 int main() 4 { 5 printf("hello, world\n"); 6 } 1.1 信息就是位上下文 hello程序的声明周期是从一个源程序开始的&#xff0c;即程序员利用编辑器创建并保存的文本文件&#xff0c;文件名是hello.c。源程序实际上就是一个由值…

java impliments,dubbo使用GenericService泛化调用

我们项目中常见场景&#xff0c;java应用内部接口都是使用dubbo&#xff0c;某个非java应用需要调用我们的接口的时候&#xff0c;无法使用dubbo&#xff0c;这是我们需要给它提供其他形式的接口&#xff0c;如restful api等等&#xff0c;这时我们需要为这个接口开发而增加额外…

使用Eclipse 创建 搭建SpringBoot项目

之前用IDEA 创建Springboot 项目感觉十分简单&#xff0c;但是常用的毕竟是Eclipse 所以开一个帖子记录一下Eclipse 如何创建 Springboot 项目 第一步&#xff1a;Help -> Eclipse Marketplace… 在search 中输入 STS install 即可&#xff01; 第二部&#xff1a;new -&g…

static函数与普通函数区别

全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式&#xff0c; 静态全局变量当然也是静态存储方式。这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序&#xff0c; 当一个源程序由多个源文件…

zendguard php5.4,ZendGuardLoader6.0.0支持PHP5.4.x系列

不知不觉&#xff0c;现在Zend Guard Loader发布了6.0.0版本&#xff0c;支持PHP 5.4.x系列。官方地址&#xff1a;http://www.zend.com/en/products/guard/downloads (需要注册用户后下载)这里提供下常用的版本Windows&#xff1a;附件&#xff1a;ZendGuardLoader-70429-PHP-…

camel mq_Camel:构建基于消息的应用程序

camel mq这是一篇长文章&#xff0c;包含三个单独的主题&#xff1a; Java的Apache Camel入门 使用CamelRunner改善路线的启动 使用Camel构建基于消息的应用程序 但是&#xff0c;由于我准备了包含所有这些材料的camel-demo-1.0.0-SNAPSHOT-project.zip &#xff0c;因此我认…

what??|诞生才一年的BCH竟面临硬分叉的抉择

BCH才刚过一周岁生日一个星期&#xff0c;BCH社区的主力之一Bitcoin ABC&#xff08;BCH全网接近三分之二节点运行的软件系统由Bitcoin ABC开发&#xff09;就搅动了社区的涟漪。8月8号&#xff0c;Bitcoin ABC公布了自己的路线图提出修改BCH的共识协议。而BCH社区的大V之一Cra…

改变div php,JS改变DIV样式

摘要&#xff1a;var boxwindow.οnlοadfunction(){box document.getElementById("box")}function aa(){box.style.height "400px"}function bb(){box.style.width "400px"}function cc(){box.style.backgroundColor "blue"}批改老…

switch变量的作用 域问题

&#xfeff;&#xfeff;switch是我们做条件选择时&#xff0c;经常用到的一个语句。一直以来对于他的使用相信大家也都是得心应手&#xff0c;前几天在linux下写一个c程序时遇到了这样的一个问题&#xff0c;请看例子&#xff1a;#include<iostream>using namespace st…

返回CompletableFuture:Java 8功能亮点

CompletableFuture与未来&#xff1a;与Java 8新功能保持异步 Java 8于2014年3月发布&#xff0c;并附带了许多新功能。 鲜为人知的&#xff0c;极为有用却被人误解的功能之一是对Future接口的全新改进&#xff0c;即扩展&#xff1a;CompletableFuture <T>。 在下面的…

php 操作 mysql 数据库常用方法集合

参考&#xff1a; https://www.runoob.com/php/php-pdo.html https://www.cnblogs.com/feng18/p/6523646.html https://blog.csdn.net/zuiliannvshen/article/details/78247244 转载于:https://www.cnblogs.com/gavinyyb/p/9543844.html

接口功能测试策略

由于平台服务器是通过接口来与客户端交互数据提供各种服务&#xff0c;因此服务器测试工作首先需要进行的是接口测试工作。测试人员需要通过服务器接口功能测试来确保接口功能实现正确&#xff0c;那么其他测试人员进行客户端与服务器结合的系统测试过程中&#xff0c;就能够排…

matlab中sort(d),MATLAB中排序函数sort()的用法

MATLAB中排序函数sort()可以对参数的元素进行升序排序或降序排序。具体的用法如下&#xff1a;Ysort(X)sort()的参数可以是向量&#xff0c;矩阵&#xff0c;数组等等。当X是向量时&#xff0c;sort(X)对X的元素进行升序排序&#xff1b;当X是矩阵时&#xff0c;sort(X)对X的每…

cin、cin.get()、cin.getline()、getline()、gets()函数的用法

1、cin>> 用法1&#xff1a;最基本&#xff0c;也是最常用的用法&#xff0c;输入一个数字&#xff1a; #include <iostream> using namespace std; main () { int a,b; cin>>a>>b; cout<<ab<<endl; } 输入&#xff1a;2[回车]3…

BootCDNApi使用记录

通过API获取BootCDN所加速的所有前端开源库的基本信息和文件列表 API 将一下API链接中的.min字样去掉后,获取到的JSON格式的返回信息是经过良好的格式化的,便于查看. 所有开源库简要信息列表 https://api.bootcdn.cn/libraries.min.json 该列表是一个json数组,数组中的每一个条…

spring防止爬虫_Spring安全:防止暴力攻击

spring防止爬虫Spring Security可以为您做很多事情。 帐户被封锁&#xff0c;密码盐。 但是蛮力阻断剂呢&#xff1f; 那是你必须自己做的。 幸运的是&#xff0c;Spring是一个非常灵活的框架&#xff0c;因此对其进行配置并不是什么大问题。 让我向您展示一些如何针对Grai…

php 输出读取结果集,php获取数据库结果集实例详解

下面小编就为大家带来一篇php获取数据库结果集方法(推荐)。小编觉得挺不错的&#xff0c;现在就分享给大家&#xff0c;也给大家做个参考。一起跟随小编过来看看吧PHP经常要访问数据库提前数据库里面的数据&#xff0c;那么该怎么样去提前数据呢&#xff1f;提取数据库代码如下…