【C++高阶(七)】C++异常处理的方式

💓博主CSDN主页:杭电码农-NEO💓

⏩专栏分类:C++从入门到精通⏪

🚚代码仓库:NEO的学习日记🚚

🌹关注我🫵带你学习C++
  🔝🔝


在这里插入图片描述

异常处理的方式

  • 1. 前言
  • 2. C语言处理异常的方式
  • 3. C++异常概念
  • 4. 异常的抛出和匹配原则
  • 5. 异常的重新抛出
  • 6. RAII思想在异常体系中的使用
  • 7. 自定义异常体系
  • 8. C++标准库的异常体系
  • 9. 总结以及拓展

1. 前言

C++有一套独立的异常处理机制,
相信大家一定听说过try,catch这两
个词,今天就来做详细的介绍

本章重点:

本篇文章着重讲解C++异常处理的方式,
三个关键字,tyr,catch,throw,并且介绍异
常的用法和自定义体系的异常以及智能指
针在异常处理中的使用场景.其中,会复习
C语言异常处理的方式


2. C语言处理异常的方式

最经典的处理方式:使用assert

assert的缺陷:

如果在代码中使用assert,则只在debug
模式下有效,在release模式下会失效.并且
只要有错误就会直接终止程序,这明显不符
合实际,比如说在使用微信时,由于网络问题
信息没发出去,这时直接将微信程序终止了,
这样做会被乱棍打死!

C语言还能用错误码返回异常信息

错误码errno的缺陷:

返回的错误码是一个数字,程序员还需
去查表来得知这个错误码是什么意思,
并且就算查找了错误码的信息,可能它
说的不清楚,也不好看错误信息

综上所述,C语言处理异常的方式还是
不够完美,于是祖师爷写了一套自己的


3. C++异常概念

当一个函数发现自己无法处理的错误时就可以抛出异常,让函数的直接或间接的调用者处理这个错误。

  • throw: 当问题出现时,程序会抛出一个异常。这是通过使用 throw 关键字来完成的
  • catch: 在您想要处理问题的地方,通过异常处理程序捕获异常.catch 关键字用于捕获异常
  • try: try 块中的代码标识将被激活的特定异常,它后面通常跟着一个或多个 catch 块。

使用方法:

try{int a,b;cin>>a>>b;if(b == 0)throw "除0错误"cout<<(a/b)<<endl;
}catch(string str)
{//......
}

如果有一个块抛出一个异常,捕获异常的方法会使用 try 和 catch 关键字。try 块中放置可能抛出异常的代码,try 块中的代码被称为保护代码,一旦throw后,会直接跳到catch的位置,后面的代码不会执行


4. 异常的抛出和匹配原则

异常的抛出和匹配有以下机制:

  1. 抛出的内容和捕捉的内容要一致

如果你在throw时抛出一个字符串,但是
在catch捕获异常时的参数却写的是整数
那么这个抛出的异常就不会去这个catch

try{int a,b;cin>>a>>b;if(b == 0)throw "除0错误"cout<<(a/b)<<endl;
}
catch(int flag)//类型与throw的不匹配,会跳到下面的catch
{//......
}
catch(string str)
{//......
}
  1. try可以嵌套多层

try和catch不仅仅可以在一个作用域
使用,还可以在最外层try,然后嵌套多
层函数,在最里面的函数throw!

void a(){throw "测试中";}
void b(){a()}
void c(){b()}
int main()
{try{c();}catch(string str){}
  1. throw和catch遵循就近原则

若写了多个catch,并且这些catch都
和throw的内容匹配,则会跳转到与
throw最近的内个catch中!

double Division(int a, int b)
{// 当b == 0时抛出异常if (b == 0)throw "除0错误!";elsereturn ((double)a / (double)b);
}
void Func()
{int len, time;cin >> len >> time;cout << Division(len, time) << endl;catch (const char* errmsg) {//这个catch与throw相距最近,会优先到这儿cout << errmsg << "111" << endl;}
}
int main()
{try {Func();}catch (const char* errmsg) {cout << errmsg << "222" << endl;}return 0;
}
  1. catch(...)可以捕获任意类型的异常

在公司写大工程的时候,会和很多同事
合作写代码,大家都会抛出异常,但是你
不能确定是不是所有人抛出的类型你都
有相应的catch可以接收,若抛出一个异常
没有被捕获会直接报错,所以…的作用很
明显,用来兜底!一般用于接收一些未知异常

double Division(int a, int b)
{// 当b == 0时抛出异常if (b == 0)throw "除0错误!";elsereturn ((double)a / (double)b);
}
void Func()
{int len, time;cin >> len >> time;cout << Division(len, time) << endl;catch (const char* errmsg) {//这个catch与throw相距最近,会优先到这儿cout << errmsg << "111" << endl;}
}
int main()
{try {Func();}catch (const char* errmsg) {cout << errmsg << "222" << endl;}catch(...){cout<<"未知异常"<<endl;           }return 0;
}
  1. 基类可以接受抛出的子类对象

抛出和捕获有一个例外,那就是可以抛出
子类对象,用基类捕获,这个在实际场景中
非常实用,我们会在后面详谈


5. 异常的重新抛出

有可能在捕获异常时,一次捕获不能
完全解决问题,比如我们想在main函
数中处理所有的异常,在非main函数
中打印一下异常信息然后再将异常抛
到main中统一做处理

double Division(int a, int b)
{// 当b == 0时抛出异常if (b == 0){throw "Division by zero condition!";}return (double)a / (double)b;
}
void Func()
{// 这里可以看到如果发生除0错误抛出异常,另外下面的array没有得到释放。// 所以这里捕获异常后并不处理异常,异常还是交给外面处理,这里捕获了再// 重新抛出去。int* array = new int[10];try {int len, time;cin >> len >> time;cout << Division(len, time) << endl;}catch (...){cout << "delete []" << array << endl;delete[] array;throw;}cout << "delete []" << array << endl;delete[] array;
}
int main()
{try{Func();}catch (const char* errmsg){cout << errmsg << endl;}return 0;
}

在上面的场景中,如果抛出异常,就会
直接走到catch处,不会调用delete释放
释放在堆上开辟的空间,就会有问题,所
以第一次catch时先处理释放空间的问题
然后将异常再次抛出后再处理异常问题


6. RAII思想在异常体系中的使用

如果你不知道什么是RAII思想,不知道
什么是智能指针,请先阅读这篇文章:

智能指针RAII思想讲解

在异常体系中在堆上申请空间,或者
打开某个问题时常容易出问题,因为
堆上开辟的空间要显示调用delete处理
而打开的文件也要显示调用fclose关闭
所以一旦发生异常就会直接跳转到catch
的位置,有可能直接忽略了释放函数
这也就是导致了资源并没有被释放!

在异常体系中最好使用RAII思想申请资源
即使抛出异常后直接跳到catch也没问题
当出了对象作用域会自动调用析构释放!

double Division(int a, int b)
{// 当b == 0时抛出异常if (b == 0){throw "Division by zero condition!";}return (double)a / (double)b;
}
void Func()
{shared_ptr<int> array(new int(10));try {int len, time;cin >> len >> time;cout << Division(len, time) << endl;}
}
int main()
{try{Func();}catch (const char* errmsg){cout << errmsg << endl;}return 0;
}

7. 自定义异常体系

实际使用中很多公司都会自定义自己的异常体系进行规范的异常管理,因为一个项目中如果大家随意抛异常,那么外层的调用者基本就没办法玩了,所以实际中都会定义一套继承的规范体系。这样大家抛出的都是继承的派生类对象,捕获一个基类就可以了

在这里插入图片描述
不同的部分可以抛出不同的异常,然后在总的main函数中使用基类捕获所有的异常再来进行特殊的处理


8. C++标准库的异常体系

这里的内容属于了解范畴,用几张图
带大家了解一下:

在这里插入图片描述

在这里插入图片描述

实际中都是我们自己去实现一个异常体系
因为C++库做的并不好


9. 总结以及拓展

异常总体而言,利大于弊,所以工程中我们还是鼓励使用异常的。另外OO的语言基本都是用异常处理错误,这也可以看出这是大势所趋。

除此之外,异常还有一套规范,因为
比较鸡肋,所以放在了最后来介绍:

  1. 异常规格说明的目的是为了让函数使用者知道该函数可能抛出的异常有哪些。 可以在函数的后面接throw(类型),列出这个函数可能抛掷的所有异常类型。
  2. 函数的后面接throw(),表示函数不抛异常。
  3. 若无异常接口声明,则此函数可以抛掷任何类型的异常。
// 这里表示这个函数会抛出A/B/C/D中的某种类型的异常
void fun() throw(A,B,C,D);
// 这里表示这个函数只会抛出bad_alloc的异常
void* operator new (std::size_t size) throw (std::bad_alloc);
// 这里表示这个函数不会抛出异常
void* operator delete (std::size_t size, void* ptr) throw();
// C++11 中新增的noexcept,表示不会抛异常
thread() noexcept;
thread (thread&& x) noexcept;

之所以比较鸡肋是因为就算你写了
noexcept,再抛出异常
在某些编译器也不会报错


🔎 下期预告:单例模式&特殊类设计🔍

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

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

相关文章

Transformer架构详解

文章目录 引言1. Transformer架构详解1.1 编码器与解码器1.1.1 编码器&#xff08;Encoder&#xff09;1.1.2 解码器&#xff08;Decoder&#xff09; 2. 核心代码2.1 自注意力&#xff08;Self-Attention&#xff09;机制2.2 多头注意力&#xff08;Multi-Head Attention&…

Python PIP安装pycorrector、kemln报错

本来想装个pycorrector用一下&#xff0c;结果在安装其依赖包kemln的时候疯狂报错&#xff0c;报错关键词包括但不限于Bash、Cmake&#xff0c;C啥的&#xff0c;搜了很多文章&#xff0c;终于摸索到了安装的办法。 1、安装bash 去官网https://gitforwindows.org/下载bash&am…

消费者痛点怎么分析,不同行业如何营销

消费者的痛点是品牌营销中的关键因素&#xff0c;因为准确把握消费者的痛点&#xff0c;可以为品牌带来更大的市场机会。今天和大家探讨下消费者痛点怎么分析&#xff0c;不同行业如何营销&#xff1f; 今天我们会从分类、洞察、场景分析、分级与评判以及不同行业细分的角度来进…

neuq-acm预备队训练week 9 P8604 [蓝桥杯 2013 国 C] 危险系数

题目背景 抗日战争时期&#xff0c;冀中平原的地道战曾发挥重要作用。 题目限制 题目描述 地道的多个站点间有通道连接&#xff0c;形成了庞大的网络。但也有隐患&#xff0c;当敌人发现了某个站点后&#xff0c;其它站点间可能因此会失去联系。 我们来定义一个危险系数 DF…

Android动画(四)——属性动画ValueAnimator的妙用

目录 介绍 效果图 代码实现 xml文件 介绍 ValueAnimator是ObjectAnimator的父类&#xff0c;它继承自Animator。ValueAnimaotor同样提供了ofInt、ofFloat、ofObject等静态方法&#xff0c;传入的参数是动画过程的开始值、中间值、结束值来构造动画对象。可以将ValueAnimator看…

环境搭建及源码运行_java环境搭建_maven

书到用时方恨少、觉知此时要躬行&#xff1b;拥有技术&#xff0c;成就未来&#xff0c;抖音视频教学地址&#xff1a;​​​​​​​ ​​​​​​​ 1、介绍 1&#xff09;管理项目依赖和版本 统一的项目依赖和版本管理 ​​​​​​​​​​​ 2&#xff09;Maven支持多模块…

From Human Attention to Computational Attention (1)

”is the taking possession by the mind, in clear and vivid form, of one out of what seem several simultaneously possible objects or trains of thought. It implies withdrawal from some things in order to deal effectively with others“&#xff0c;William Jame…

6.任务分配与执行总体设计实现

1.设计 执行任务找一个落地场景&#xff1a;连接设备采集参数。设备有不同的协议&#xff0c;如&#xff1a;modbus rtu、modbus tcp、opc ua、simens s7等。协议多种多样&#xff0c;需要的参数也不同&#xff0c;连接及任务执行参数存放在t_job表的link_spec中&#xff0c;任…

Jenkins配置代理节点时遇到的坑和解决办法

需求&#xff1a;服务器太满了&#xff0c;需要找个比较空闲的机器分担一下&#xff0c;看上了同网络的某开会用的笔记本&#xff0c;把这个本本利用起来能跑一个算一个。 但配置起来并不容易&#xff0c;遇到的问题有些网上也几乎找不到答案。这里记录一下能救一个是一个&…

python处理数据内存不够,python处理数据安全吗

大家好&#xff0c;小编为大家解答python处理数据索引的常见方法的问题。很多人还不知道python处理数据内存不够&#xff0c;现在让我们一起来看看吧&#xff01; 学 目录 1.数据表的基本信息查看 2.查看数据表的大小 3.数据格式的查看 4、查看具体的数据分布 二、缺失值处理 …

sap table 获取 valuation class MBEW 查表获取

参考 https://www.tcodesearch.com/sap-tables/search?qvaluationclass

FastAPI访问/docs接口文档显示空白、js/css无法加载

如图&#xff1a; 原因是FastAPI的接口文档默认使用https://cdn.jsdelivr.net/npm/swagger-ui-dist5.9.0/swagger-ui.css 和https://cdn.jsdelivr.net/npm/swagger-ui-dist5.9.0/swagger-ui-bundle.js 来渲染页面&#xff0c;而这两个URL是外网的CDN&#xff0c;在国内响应超…

Text2SQL学习整理(二) WikiSQL数据集介绍

导语 上篇博客中&#xff0c;我们已经了解到Text2SQL任务的基本定义&#xff0c;本篇博客将对近年来该领域第一个大型数据集WikiSQL做简要介绍。 WikiSQL数据集概述 基本统计特性 WikiSQL数据集是一个多数据库、单表、单轮查询的Text-to-SQL数据集。它是Salesforce在2017年…

python之双链表

双链表简单讲解 双向链表&#xff08;doubly linked list&#xff09;是一种链式数据结构&#xff0c;它的每个节点包含两个指针&#xff0c;一个指向前一个节点&#xff0c;一个指向后一个节点。与单向链表相比&#xff0c;双向链表可以在任何位置进行插入和删除操作&#xf…

PDF转为图片

PDF转为图片 背景pdf展示目标效果 发展过程最终解决方案&#xff1a;python PDF转图片pdf2image注意&#xff1a;poppler 安装 背景 最近接了一项目&#xff0c;主要的需求就是本地的文联单位&#xff0c;需要做一个电子刊物阅览的网站&#xff0c;将民族的刊物发布到网站上供…

字节开源的netPoll多路复用器源码解析

字节开源的netPoll多路复用器源码解析 引言NetPollepoll API原生网络库实现netpoll 设计思路netpoll 对比 go net数据结构 源码解析多路复用池初始化Epoll相关API可读事件处理server启动accept 事件客户端连接初始化客户端连接建立 可读事件等待读取数据 可写事件处理客户端启动…

word增加引用-endnote使用

使用软件&#xff1a; web of science https://webofscience.clarivate.cn/wos/alldb/basic-search; Pub Med等数据库endnote20 链接: https://pan.baidu.com/s/1VQMEsgFY3kcpCNfIyqEjtQ?pwdy1mz 提取码: y1mz 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 --…

信号与线性系统翻转课堂笔记4——连续LTI系统的微分方程模型与求解

信号与线性系统翻转课堂笔记4——连续LTI系统的微分方程模型与求解 The Flipped Classroom4 of Signals and Linear Systems 对应教材&#xff1a;《信号与线性系统分析&#xff08;第五版&#xff09;》高等教育出版社&#xff0c;吴大正著 一、要点 &#xff08;1&#x…

探索 Coinbase 二层链 Base 的潜力与风险

作者&#xff1a;lesleyfootprint.network 在不断变化的加密货币领域&#xff0c;Coinbase 已经确立了自己领先中心化交易所&#xff08;CEX&#xff09;的地位。然而&#xff0c;Coinbase 坚信去中心化是创造一个开放、全球范围内对每个人都可访问的加密经济的关键&#xff0…

python学习3

大家好&#xff0c;今天又来更新python学习篇了。本次的内容比较简单&#xff0c;时描述性统计代码&#xff0c;直接给出所有代码&#xff0c;如下&#xff1a; import pandas as pd from scipy.stats import fisher_exact from fuzzywuzzy import fuzz from fuzzywuzzy impor…