0.目录

1.异常规格说明

2.unexpected() 函数

3.小结

1.异常规格说明

问题:

如何判断一个函数是否会抛出异常,以及抛出哪些异常?

  • C++提供语法用于声明函数所抛出的异常
  • 异常声明作为函数声明的修饰符,写在参数列表后面

异常规格说明的意义:

  • 提示函数调用者必须做好异常处理的准备
  • 提示函数的维护者不要抛出其它异常
  • 异常规格说明是函数接口的一部分

问题:

如果抛出的异常不在声明列表中,会发生什么?

下面的代码的输出什么?

示例——异常规格之外的异常:

  1. #include <iostream>
  2. using namespace std;
  3. void func() throw(int)
  4. {
  5. cout << "func()";
  6. cout << endl;
  7. throw 'c';
  8. }
  9. int main()
  10. {
  11. try
  12. {
  13. func();
  14. }
  15. catch(int)
  16. {
  17. cout << "catch(int)";
  18. cout << endl;
  19. }
  20. catch(char)
  21. {
  22. cout << "catch(char)";
  23. cout << endl;
  24. }
  25. return 0;
  26. }

运行结果为:

  1. [root@bogon Desktop]# g++ test.cpp
  2. [root@bogon Desktop]# ./a.out
  3. func()
  4. terminate called after throwing an instance of 'char'
  5. Aborted (core dumped)

(不同编译器运行结果不一样。)

2.unexpected() 函数

  • 函数抛出的异常不在规格说明中,全局 unexpected() 被调用
  • 默认的 unexpected() 函数会调用全局的 terminate() 函数
  • 可以自定义函数替换默认的 unexpected() 函数实现
  • 注意:不是所有的C++编译器都支持这个标准行为

unexpected() 函数的替换:

  • 自定义一个无返回值无参数的函数

    1. 能够再次抛出异常

      1. 当异常符合触发函数的异常规格说明时,恢复程序执行
      2. 否则,调用全局 terminate() 函数结束程序
  • 调用 set_unexpected () 设置自定义的异常函数
    1. 参数类型为 void (*) ()
    2. 返回值为默认的 unexpected() 函数入口地址

示例1——自定义 unexpected() 函数:

  1. #include <iostream>
  2. #include <cstdlib>
  3. #include <exception>
  4. using namespace std;
  5. void my_unexpected()
  6. {
  7. cout << "void my_unexpected()" << endl;
  8. exit(1);
  9. }
  10. void func() throw(int)
  11. {
  12. cout << "func()";
  13. cout << endl;
  14. throw 'c';
  15. }
  16. int main()
  17. {
  18. set_unexpected(my_unexpected);
  19. try
  20. {
  21. func();
  22. }
  23. catch(int)
  24. {
  25. cout << "catch(int)";
  26. cout << endl;
  27. }
  28. catch(char)
  29. {
  30. cout << "catch(char)";
  31. cout << endl;
  32. }
  33. return 0;
  34. }

运行结果为:

  1. [root@bogon Desktop]# g++ test.cpp
  2. [root@bogon Desktop]# ./a.out
  3. func()
  4. void my_unexpected()

exit();改为throw 1;后的运行结果:

示例2——自定义 unexpected() 函数:

  1. void my_unexpected()
  2. {
  3. cout << "void my_unexpected()" << endl;
  4. // exit(1);
  5. throw 1;
  6. }

运行结果为:

  1. [root@bogon Desktop]# g++ test.cpp
  2. [root@bogon Desktop]# ./a.out
  3. func()
  4. void my_unexpected()
  5. catch(int)

(程序恢复执行了。)

(unexpected() 函数是正确处理异常的最后机会,如果没有抓住这次机会,全局的 terminate() 函数就会被调用,当前程序就只能以异常结束告终。)

3.小结

  • C++中的函数可以声明异常规格说明
  • 异常规格说明可以看作接口的一部分
  • 函数抛出的异常不在规格说明中,unexpected() 被调用
  • unexpected() 中能够再次抛出异常
    1. 异常能够匹配,恢复程序的执行
    2. 否则,调用 terminate() 结束程序

C++解析-外传篇(2):函数的异常规格说明的更多相关文章

  1. C++解析-外传篇(3):动态内存申请的结果

    0.目录 1.动态内存申请一定成功吗? 2.new_handler() 函数 3.小结 1.动态内存申请一定成功吗? 问题: 动态内存申请一定成功吗? 常见的动态内存分配代码: C代码: C++代码: ...

  2. C++解析-外传篇(1):异常处理深度解析

    0.目录 1.异常的最终处理 2.结束函数terminate() 3.小结 1.异常的最终处理 问题: 如果在main函数中抛出异常会发生什么? 如果异常不处理,最后会传到哪里? 下面的代码的输出什么 ...

  3. jQuery2.x源码解析(回调篇)

    jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 通过艾伦的博客,我们能看出,jQuery的pro ...

  4. DEX文件解析--7、类及其类数据解析(完结篇)

    一.前言    前置技能链接:       DEX文件解析---1.dex文件头解析       DEX文件解析---2.Dex文件checksum(校验和)解析       DEX文件解析--3.d ...

  5. jQuery2.x源码解析(缓存篇)

    jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 缓存是jQuery中的又一核心设计,jQuery ...

  6. jQuery2.x源码解析(构建篇)

    jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 笔者阅读了园友艾伦 Aaron的系列博客< ...

  7. jQuery2.x源码解析(设计篇)

    jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 这一篇笔者主要以设计的角度探索jQuery的源代 ...

  8. PE文件解析 基础篇

    PE文件解析 基础篇 来源 https://bbs.pediy.com/thread-247114.htm 前言 之前学习了PE格式,为了更好的理解,决定写一个类似LoadPE的小工具. 编译器是VS ...

  9. 自定义UDF函数应用异常

    自定义UDF函数应用异常 版权声明:本文为yunshuxueyuan原创文章.如需转载请标明出处: http://www.cnblogs.com/sxt-zkys/QQ技术交流群:299142667 ...

随机推荐

  1. HttpClient使用详解 (一)

    Http协议的重要性相信不用我多说了,HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性(具体区别,日后我们再讨论),它不仅是客户端发送Http请求变得容易,而且 ...

  2. Linux命令之tar命令

    [root@linux ~]# tar [-cxtzjvfpPN] 文件与目录 .... 参数: -c :建立一个压缩文件的参数指令(create 的意思): -x :解开一个压缩文件的参数指令! - ...

  3. HP VC模块Server Profile配置快速参考(With SUS)

    以管理员身份登录VCM 准备进行Server Profiles的配置 在左侧导航栏中找到并点击"Server Profiles",在右侧主窗口的左下角点击"Add&quo ...

  4. hdu - 6282,2018CCPC湖南全国邀请赛G题,字符串,规律

    HDU – 6282 http://acm.hdu.edu.cn/showproblem.php?pid=6282 by Hzu_Tested 题意:给出两个字符串S和T,只由a,b,c三种字符组成( ...

  5. libCurl 初步认识 - cur easy

    cur easy接口简洁明了,主接口4个,辅接口5个. 主接口 初始化 + 配参数 + 执行 + 销毁 初始化 CURL* curl_easy_init() 获得CURL句柄,返回值需要判空. 配参数 ...

  6. AirSim的搭建和使用

    由于自己使用设备拍摄的数据质量太差,所以决定使用AirSim这个框架来生成数据.之所以使用这个框架,是因为之前同事用其生成了一些有效数据. 当然,我是不可能把我搭建的步骤一一写出来的,一来是因为太麻烦 ...

  7. Jenkins之Sonar 代码检查

    一.简介 SonarQube 是一个用于代码质量管理的开放平台.通过插件机制,Sonar 可以集成不同的测试工具,代码分析工具,以及持续集成工具.与持续集成工具(例如 Hudson/Jenkins 等 ...

  8. 5 种使用 Python 代码轻松实现数据可视化的方法

    数据可视化是数据科学家工作中的重要组成部分.在项目的早期阶段,你通常会进行探索性数据分析(Exploratory Data Analysis,EDA)以获取对数据的一些理解.创建可视化方法确实有助于使 ...

  9. MYSQL报警:Warning: Using a password on the command line interface can be insecure.

    问题描述:执行下面的语句,sql是执行成功了,但是出现了一个报警,报警看上去始终不舒服 mysql -hip -Pport -uuser -ppassword -e "use db;dele ...

  10. Python:迭代器的简单理解

    一.什么是迭代器 迭代,顾名思义就是重复做一些事很多次(就现在循环中做的那样).迭代器是实现了__next__()方法的对象(这个方法在调用时不需要任何参数),它是访问可迭代序列的一种方式,通常其从序 ...