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,一经查实,立即删除!

相关文章

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;帮助读者理解并快速上手开发。同时&#…

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;用于自动剪辑。该插件能够识别和处理视频和音频素材…

飞天使-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编…

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;可以纳入商用空调范畴的产品可以包括户式中央空调产品、部分传统中央空调产品以及部分家用空调。商用空调已普遍采用直流变频领先技…

泡沫玻璃市场分析:预计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…

优思学院|如何建立公司运营指标体系?如何推行六西格玛改进运营指标?

关键绩效指标 (KPI) 是测量您团队或组织朝重要商业目标进展表现如何的量化指标&#xff0c;组织会在多个层面使用 KPI&#xff0c;这视乎您想要追踪何指标而定&#xff0c;您可以设定全组织的、特定团队的、或甚至是个人 KPI。 良好的KPI能让公司管理者掌握组织的营运是否进度…

使用React 18、Echarts和MUI实现温度计

关键词 React 18 Echarts和MUI 前言 在本文中&#xff0c;我们将结合使用React 18、Echarts和MUI&#xff08;Material-UI&#xff09;库&#xff0c;展示如何实现一个交互性的温度计。我们将使用Echarts绘制温度计的外观&#xff0c;并使用MUI创建一个漂亮的用户界面。 本文…

点评项目——分布式锁

2023.12.10 集群模式下的并发安全问题及解决 随着现在分布式系统越来越普及&#xff0c;一个应用往往会部署在多台机器上&#xff08;多节点&#xff09;&#xff0c;通过加锁可以解决在单机情况下的一人一单安全问题&#xff0c;但是在集群模式下就不行了。见下图&#xff1a…

在 Android WebView 中实现和 JavaScript 的互操作

前言 在 APP 中内嵌一个 H5 来实现特定的业务功能已经是非常成熟且常用的方案了。 虽然 H5 已经能够实现大多数的需求&#xff0c;但是对于某些需求还是得依靠原生代码来实现然后与 JavaScript 进行交互&#xff0c;例如我目前所负责的项目就是一个 “智能硬件” 设备&#x…

【PyTorch】卷积神经网络

文章目录 1. 理论介绍1.1. 从全连接层到卷积层1.1.1. 背景1.1.2. 从全连接层推导出卷积层 1.2. 卷积层1.2.1. 图像卷积1.2.2. 填充和步幅1.2.3. 多通道 1.3. 池化层&#xff08;又称汇聚层&#xff09;1.3.1. 背景1.3.2. 池化运算1.3.3. 填充和步幅1.3.4. 多通道 1.4. 卷积神经…

实现React18加TS,解决通用后台管理系统,实战方案落地有效实践经验

随着前端技术的不断发展和更新&#xff0c;使用React 18结合TypeScript&#xff08;TS&#xff09;来构建通用后台管理系统已成为一种常见的选择。本文将介绍如何在项目中应用React 18和TS&#xff0c;并分享一些实战方案的有效实践经验。 一、搭建React 18 TS项目 首先&…

12.2每日一题(1无穷型幂指函数:二倍角公式+三部曲+等价无穷小代换(只有整体的因子不为0才能先算出来))

注意&#xff1a;求极限不能想先算哪里就先算哪里&#xff0c;只有整体的因子不为0才能先算出来&#xff0c;部分不为0不可以先算

外贸老业务也棘手的一个问题

这几天有2个老业务都被一个类同的问题缠住了。 客户定购了三台车&#xff0c;由于是非常规要求所以我建议收取全款或者最少收50%的定金。但是业务员为了当月业绩或者为了拿到就收了客户20% 或者30% &#xff0c;定金收到了&#xff0c;我也不好再逼着业务员去加收定金。 订单就…