13、C++异常处理

13、c++异常处理

  • 抛出异常
  • 捕获异常
  • 未抛出异常时的流程
  • 抛出异常时的流程
  • 捕获异常
  • 匹配顺序
  • 异常说明
  • 异常处理
  • 构造函数中的异常
  • 析构函数中的异常
  • 标准库异常类

抛出异常

  • throw 异常对象
  • 可以抛出基本类型的对象,如:throw -1;throw "内存分配失败!";
  • 也可以抛出类类型的对象,如:MemoryException ex;throw ex;throw MemoryException();
  • 但不要抛出局部对象的指针,如:MemoryException ex;throw &ex; // 错误!

捕获异常

try {
可能引发异常的语句
}
catch (异常类型1& ex){针对异常类型1的异常处理;}
catch (异常类型2& ex) {针对异常类型2的异常处理;}
...
catch (异常类型n& ex) {针对异常类型n的异常处理;}

未抛出异常时的流程

在这里插入图片描述

抛出异常时的流程

在这里插入图片描述

捕获异常

  • 建议在catch子句中使用引用接收异常对象,避免因为拷贝构造带来性能损失
  • 推荐以匿名临时对象的形式抛出异常
  • 异常对象必须允许被拷贝构造和析构

匹配顺序

根据异常对象的类型自上至下顺序匹配,而非最优匹配,因此对子类类型异常的捕获不要放在对基类类型异常的捕获后面

异常说明

异常说明是函数原型的一部分,旨在说明函数可能抛出的异常类型
返回类型 函数名(形参表) throw (异常类型1,异常类型2,...) {函数体;}

异常说明是一种承诺,承诺函数不会抛出异常说明以外的异常类型
如果函数抛出了异常说明以外的异常类型,那么该异常将无法被捕获并导致进程中止

隐式抛出异常的函数也可以列出它的异常说明

异常说明可以没有也可以为空

  • 没有异常说明,表示可能抛出任何类型的异常
    • void foo (void) { ... }
  • 异常说明为空,表示不会抛出任何类型的异常
    • void foo (void) throw () { ... }

异常说明在函数的声明和定义中必须保持严格一致,否则将导致编译错误

异常处理

  • 可以抛出基本类型的异常
  • 可以抛出类类型的异常
  • 利用类类型的异常,携带更多诊断信息,以便查错
  • 可以在catch块中继续抛出所捕获的异常,或其它异常
  • 任何未被捕获的异常,默认的处理方式就是中止进程
  • 忽略异常,不做处理

构造函数中的异常

构造函数可以抛出异常,某些时候还必须抛出异常

  • 构造过程中可能遇到各种错误,比如内存分配失败
  • 构造函数没有返回值,无法通过返回值通知调用者

构造函数抛出异常,对象将被不完整构造,而一个被不完整构造的对象,其析构函数永远不会被执行

  • 所有对象形式的成员变量,在抛出异常的瞬间,都能得到正确地析构 (构造函数的回滚机制)
  • 所有动态分配的资源,必须在抛出异常之前,自己手动释放,否则将形成资源的泄漏

析构函数中的异常

不要从析构函数中主动抛出异常

在两种情况下,析构函数会被调用

  • 正常销毁对象,离开作用域或显式delete
  • 在异常传递的堆栈辗转开解(stack-unwinding)过程中

对于第二种情况,异常正处于激活状态,而析构函数又抛出了异常这时C++将通过std::terminate()函数,令进程中止
对于可能引发异常的操作,尽量在析构函数内部消化
try {... }catch (...) { ... }

标准库异常类

在这里插入图片描述

// 利用return报告异常信息
#include <iostream>
#include <cstdio>
using namespace std;class A{
public:A() {  cout << "A()被调用" << endl; }~A(){  cout << "~A()被调用" << endl; }
};void foo(){cout << "foo出错前的几百行代码" << endl;A a;FILE* pfile = fopen("./cfg","r");if(!pfile)throw -1;cout << "foo出错后的几百行代码" << endl;
} // a.~A() 释放a本身所占内存空间void bar(){cout << "bar出错前的几百行代码" << endl;A b;
//    try{foo();
//    }
//    catch(int e){
//        cout << "bar函数中捕获异常信息: " << e << endl;
//    }cout << "bar出错后的几百行代码" << endl;
} // b.~A() 释放b本身所占内存空间void hum(){cout << "hum出错前的几百行代码" << endl;A c;try{bar();}catch(int e){cout << "hum函数中捕获异常信息:" << e << endl;}cout << "bar出错后的几百行代码" << endl;
} // c.~A() 释放c本身所占内存空间int main( void ){cout << "main出错前的几百行代码" << endl;A d;hum();cout << "main出错后的几百行代码" << endl;return 0;
} // d.~A() 释放d本身所占内存空间
// 建议将子类类型异常捕获放到基类类型异常捕获的前面
#include <iostream>
using namespace std;class A{};class B : public A{};void foo(){throw B();
}int main( void ){try{foo();}catch(B& b){  cout << "B类型catch捕获" << endl;}catch(A& a){  cout << "A类型catch捕获" << endl;}return 0;
} 
// 没有异常说明和异常说明为空
#include <iostream>
using namespace std;void foo()  { // 没有异常说明:函数内部可能抛出任何类型的异常throw  "Hello world!"; // 3.14; // -1;
}void bar() throw(){ // 异常说明为空:承诺函数内部绝对不会抛出任何类型的异常
//  throw -1;
}
// 异常说明在声明和定义时必须严格一致,否则将报编译错误
void hum() throw(int,double);  // 声明
void hum() throw(int,double){ // 定义
}int main( void ){try{foo();
//     bar();}catch( ... ){ // 忽略异常// ...}/*    catch(int& e){cout << "1. 捕获异常信息:"<< e << endl; }catch(double& e){cout << "2. 捕获异常信息:" << e << endl;}catch(const char* e){cout << "3. 捕获异常信息:" << e << endl;}*/return 0;
} 
// 构造函数中的异常
#include <iostream>
#include <cstdio>
using namespace std;class A{
public:A(){ cout << "A()被调用" << endl; }~A(){ cout << "~A()被调用" << endl; }
};
class C{
public:C():m_p(new int){//【A m_a;】定义m_a,利用m_a.A()//【int* m_p = new int;】定义m_p,初值指向一块堆内存(动态资源)cout << "C()被调用" << endl;FILE* pfile = fopen("./cfg","r");if(!pfile){delete m_p; // 需要自己手动释放// 对于m_a.利用m_a.~A()// 释放m_a/m_p本身所占内存空间throw -1;}// ....构造函数中后续代码...}~C(){delete m_p;cout << "~C()被调用" << endl;// 对于m_a.利用m_a.~A()// 释放m_a/m_p本身所占内存空间}
private:A m_a;int* m_p;
};int main( void ){try{C c; // 定义c,利用c.C();}// 如果c是完整构造对象,将利用c.~C(),但是如果c是残缺对象,就不会调用~C()catch( ... ){// ...}return 0;
} 

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

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

相关文章

AVP对纵向控制ESP(Ibooster)的需求规范

目录 1. 版本记录... 3 2. 文档范围和控制... 4 2.1 目的/范围... 4 2.2 文档冲突... 4 2.3 文档授权... 4 2.4 文档更改控制... 4 3. 功能概述... 5 4. 系统架构... 6 5. 主要安全目标... 7 5.1 …

FreeSSL申请免费域名证书

本文详细讲解如何申请免费证书&#xff0c;需要先准备好域名&#xff0c;将服务器IP和域名绑定。 1、注册FreeSSL账号 网址&#xff1a; https://freessl.org/ 2、申请流程 登录后首页输入域名&#xff0c;然后点击Create certificate&#xff0c;跳转到证书申请页面。 或者…

Pytorch深度强化学习1-6:详解时序差分强化学习(SARSA、Q-Learning算法)

目录 0 专栏介绍1 时序差分强化学习2 策略评估原理3 策略改进原理3.1 SARSA算法3.2 Q-Learning算法 0 专栏介绍 本专栏重点介绍强化学习技术的数学原理&#xff0c;并且采用Pytorch框架对常见的强化学习算法、案例进行实现&#xff0c;帮助读者理解并快速上手开发。同时&#…

老人的数目

给你一个下标从 0 开始的字符串 details 。details 中每个元素都是一位乘客的信息&#xff0c;信息用长度为 15 的字符串表示&#xff0c;表示方式如下&#xff1a; 前十个字符是乘客的手机号码。接下来的一个字符是乘客的性别。接下来两个字符是乘客的年龄。最后两个字符是乘…

QGIS 加载在线XYZ地图图层

QGIS 加载在线XYZ地图图层 定义并添加必应XYZ图层 Go to Layer > Add Layer > Add XYZ Layer…Click NewName as BingMaps(as you wish)URL as http://ecn.t3.tiles.virtualearth.net/tiles/a{q}.jpeg?g1click OkSelect XYZ Connections as Bing Maps(Which you creat…

PR自动剪辑视频工具AI智能剪辑插件AutoPod

推荐一款可以提高剪辑效率&#xff0c;节约时间成本的AI人工智能自动剪辑视频制作工具pr插件Autopod&#xff0c;辅助你更快地完成视频内容的编辑工作。 Autopod 插件是一款应用于 Adobe Premiere Pro 软件的插件&#xff0c;用于自动剪辑。该插件能够识别和处理视频和音频素材…

Spring Boot 常用注解分类

目录 1.核心注解&#xff1a;2.配置相关注解&#xff1a;3.控制器相关注解&#xff1a;4.数据访问相关注解&#xff1a;5.测试相关注解&#xff1a;6.条件注解&#xff1a;7.AOP相关注解&#xff1a;8.定时任务相关注解&#xff1a;9.消息队列相关注解&#xff1a;10.Spring Se…

函数式编程解析:定义、功能与Java实践

目录 一、函数式编程1.1 什么是函数式编程1.2 函数式编程特征1.2.1 纯函数1.2.2 函数是一等公民 1.3 函数式编程在java中的实践 参考资料 一、函数式编程 1.1 什么是函数式编程 函数式编程&#xff08;Functional Programming&#xff09;是一种编程范式&#xff0c;它将计算…

ES6中的迭代器和set、map集合

什么是迭代器&#xff1f; 一种机制&#xff0c;也是一种接口&#xff0c;为数据结构提供统一访问接口&#xff0c;依次处理数据据结构成员 只要实现了迭代器接口&#xff0c;就可以使用for...of循环遍历。 /*** 迭代器是一种机制 是一种接口 只要数据解构实现了接口 就可…

力扣labuladong一刷day36天

力扣labuladong一刷day36天 一、96. 不同的二叉搜索树 题目链接&#xff1a;https://leetcode.cn/problems/unique-binary-search-trees/ 思路&#xff1a;这是一道典型的动态规划题&#xff0c;从n3来看 子树有几种形态 (0, 2)、(1, 1)、(2, 0)有规律可循&#xff0c;即为左…

飞天使-linux操作的一些技巧与知识点4

文章目录 ansible配置文件的优先级尝试开始进行操作ansible常用模块ansible 的playbook示例安装phpplaybook中变量的引用 ansible yum install -y ansible 测试是否可用 ansible localhost -m ping /etc/ansible/ansible.cfg &#xff1a;主配置文件&#xff0c;配置 ansible…

大公司求我用Kotlin写个通用爬虫模板

bug虐我千百遍&#xff0c;我待他如初恋。每次深夜挑灯都是我与bug较量的时间。今天我要说的就是写一个爬虫模版&#xff0c;自动抓取百度图片的教程&#xff0c;这次使用Kotlin编写的爬虫程序在Scrapy框架下完成的&#xff0c;如有不足欢迎指正。 首先&#xff0c;使用Kotlin编…

Mybatis-Plus源码解析之@MapperScan(一)

group : com.baomidou version:3.5.2.2-SNAPSHOT baomidou官网可以从快速开始了解到&#xff0c;除了配置数据源&#xff0c;最重要的就是MapperScan 注解&#xff0c;在 Spring Boot 启动类中添加 MapperScan 注解&#xff0c;扫描 Mapper 文件夹。 MapperScan 按照惯例&…

angular form 组件、双向绑定;反应式表单

1.使用双向绑定&#xff0c;以及angular的表单提交功能 app.moudle中引入 双向绑定 [(ngModel)]"text" ​​​​​​​ 效果 提交表单 2.反应式表单 在app.module.ts中引入在组件中引入&#xff0c;并放在一个变量里 在初始化时实列化这个module 定义规则 在html…

Linux:环境变量

目录 1.基本变量 2.通过代码获取环境变量 2.1 main传参 2.2 全局变量environ 2.3 系统调用getenv() 3.在脚本文件中添加环境变量 4.环境变量通常是具有全局属性 1.基本变量 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数…

商用中央空调市场分析:预计2028年将达到628亿元

商用空调一直以来都没有一个相对比较明确的概念&#xff0c;一直以来被认为是制冷空调市场的一个细分子行业。现在比较一致的观点是&#xff0c;可以纳入商用空调范畴的产品可以包括户式中央空调产品、部分传统中央空调产品以及部分家用空调。商用空调已普遍采用直流变频领先技…

网络计算机模拟实现

今天给大家说说前几天完成的一个模拟的网络计算机吧&#xff0c;虽然计算机的模拟实现的原理很简单&#xff0c;但是如果要想写乘网络的&#xff0c;个人认为是不简单的。基本上算是包涵了套接字编程的三分之一的知识点&#xff0c;此处的套接字编程指的是在理解TCP/IP五层协议…

泡沫玻璃市场分析:预计2028年将达到14亿美元

泡沫玻璃最早是由美国匹兹堡康宁公司发明的&#xff0c;是由碎玻璃、发泡剂、改性添加剂和发泡促进剂等&#xff0c;经过细粉碎和均匀混合后&#xff0c;再经过高温熔化&#xff0c;发泡、退火而制成的无机非金属玻璃材料。它是由大量直径为1~2毫米的均匀气泡结构组成。其中吸声…

Linux 常用命令----mktemp 命令

文章目录 基本用法实例演示高级用法注意事项 mktemp 命令用于创建一个临时文件或目录&#xff0c;这在需要处理临时数据或进行安全性测试时非常有用。使用 mktemp 可以保证文件名的唯一性&#xff0c;避免因文件名冲突而导致的问题。 基本用法 创建临时文件: 命令 mktemp 默认…

Go语言基础知识学习(一)

Go基本数据类型 bool bool型值可以为true或者false,例子&#xff1a; var b bool true数值型 类型表示范围int8有符号8位整型-128 ~ 127int16有符号16位整型-32768 ~ 32767int32有符号32位整型-2147783648 ~ 2147483647int64有符号64位整型uint8无符号8位整型0 ~ 255uint16…