C++之异常处理

目录

一、C语言处理错误

1、终止程序

2、返回错误码

二、C++异常

异常的抛出和匹配原则

异常安全

异常规范

异常优缺点


一、C语言处理错误

传统处理错误的两种方式:

1、终止程序

使用assert是直接终止程序,包含头文件assert.h即可

缺点:出现错误直接终止程序,用户使用起来比较难受

2、返回错误码

这里的错误码在Linux中用的比较多,Linux底层就是用C语言写的

缺点:错误码比较多,出现错误后需要自己去查找对应的错误,


二、C++异常

异常是一种处理错误的方式

异常需要用到下面三个关键字:throw、catch、try

throw:当问题出现时,程序会抛一个异常

catch:catch是捕捉异常的类型

try:try是捕获的一段区域,后面跟着一个或多个catch块

下面举个简单的除数为0抛异常的例子:

先执行main函数,进入try,执行Test(),输入a、b,再进入Div函数中,判断除数即b是否为0,如果为0,则直接throw错误信息到main函数的catch语句中,打印出来:

如果输入的是正常数字,那么进入Div函数后,执行else语句,再返回到Test函数,再返回到main函数,接下来不执行catch语句,直接跳过catch语句,到return 0:


异常的抛出和匹配原则

1、异常是通过抛出对象而引发的,该对象的类型决定了应该激活哪个catch的处理代码。

例如上面的代码如果多一个catch(int err) { cout << err << endl; },现在有两个catch语句,编译器会根据throw的类型决定进入那个catch语句

2、被选中的处理代码是调用链中与该对象类型匹配且离抛出异常位置最近的那一个。

如果改变一下上面的代码:

我们在Test函数中,也加了try,catch语句,这时如果出现除0错误,throw会往回找,谁在这个调用链中离抛异常位置最近,就执行谁的catch语句,结果如下:

可见执行的是Test函数的catch语句

但是需要注意的是,如果Test函数有catch语句,但是与throw的类型不匹配,这时也不会执行Test的catch语句,需要类型匹配

如果出现特殊情况,没有一个函数中的catch与throw的类型匹配,则会直接报错,终止程序,所以异常是必须被捕获的


3、catch(...)可以捕获任意类型的异常,缺点是不知道异常错误是什么。

由于上面说到的,异常必须被捕获,但是担心出现未捕获的异常而导致程序直接崩溃,所以给最后加了一个保险的catch语句,即:catch(...),用于捕获任意类型的异常,当然优先捕获前面的异常,都匹配不上,才会匹配catch(...)

输入5 0,发生除0错误,但是没有类型匹配的catch语句,所以执行catch(...),打印出了未知错误


4、抛出异常对象后,会生成一个异常对象的拷贝,因为抛出的异常对象可能是一个临时对象, 所以会生成一个拷贝对象,这个拷贝的临时对象会在被catch以后销毁。

抛异常一般都会抛一个对象,这个对象一般都是被定义出来的,假设自己写一个Exception类,里面有错误信息与错误编号:

运行结果如下,既能打印出错误信息,又能打印出错误编号:

而main函数中的const Exception& e,也并不是引用的Div函数中创建的Exception e("发生除0错误", 2)这个e对象

因为这个e对象是临时对象,出了作用域会被销毁,所以main函数中引用的是Exception e这个e对象的拷贝对象


5、实际中抛出和捕获的匹配原则有个例外,并不都是类型完全匹配,可以抛出的派生类(子类)对象, 使用基类(父类)捕获

之所以有这个原则,是因为如果一个项目非常大,分了很多个小组做这个项目,每个小组都抛一个异常,那catch这里语句会非常多,不利于使用,所以引出了这个原则,在公司中非常有用

抛派生类对象,用基类捕获,前面学过赋值兼容转换,可以让派生类进行切割/切片处理,从而让基类捕获,所以不管多少人想要抛异常,只要继承统一的一个基类,这时只需要捕获这个基类就达到目的了

try中先调用TestAdd,然后抛AddErr异常

这里的what使用了多态的语法,父类子类都实现了what

抛异常的是子类用父类捕获,子类对象进入catch (const Exception& e)中,切片处理,调用子类的what函数,结果为:


异常安全

不要在构造函数中抛异常,否则可能导致对象不 完整或没有完全初始化

不要在析构函数内抛出异常,否则可能导致资源泄漏

C++中异常经常会导致资源泄漏的问题,比如在new和delete中抛出了异常,导致内存泄漏,死锁等问题,C++经常使用RAII来解决以上问题,关于RAII在接下来的智能指针博客进行讲解。


异常规范

C++98有下面的异常规范,需要注意的是这里的异常规范并不是强制的

①异常规范是为了让使用者知道函数可能抛出的异常有哪些,例如:

void test() throw(x, y);

表示test函数,可能会抛x/y的异常

②函数的后面接throw(),表示函数不抛异常

void test() throw();

表示test函数,不会抛异常

③若无异常接口声明,则此函数可以抛掷任何类型的异常

因为异常规范并不是强制的

④C++11新增关键字noexcept,函数的后面接throw(),表示函数不抛异常:

void test() noexcept;

表示test函数,不会抛异常


异常优缺点

优点:

1、异常相比错误码的方式可以清晰准确的展示出错误的各种信息,可以帮助我们更好的定位程序的bug。

2、返回错误码的传统方式如果返回了错误,那么我们得层层返回错误,最外层才能拿到错误,而如果是异常体系,抛出的异常异常会直接跳到main函数中catch捕获的地方,main函数会直接处理错误。

3、很多的第三方库都包含异常,比如boost、gtest、gmock等等常用的库,那么我们使用它们也需要使用异常。

4、部分函数使用异常更好处理,比如引用返回的函数(类似T&),不使用异常的话,出现越界等错误时只能终止程序

缺点:

1、异常会导致程序的执行流乱跳,因为throw不会一层层的执行

2、C++没有垃圾回收机制,资源需要自己管理。容易导致内存泄漏、死锁等异常安全问题,需要使用RAII来处理资源的管理问题

3、C++标准库的异常体系定义得不好,所以大家各自定义各自的异常体系,非常的混乱。

4、异常尽量规范使用,否则捕获时非常混乱

总而言之:异常是利大于弊的,是建议使用时规范使用


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

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

相关文章

几个测试接口的好工具,效率加倍~

作为一名后端程序员&#xff0c;一定要对自己写的接口负责&#xff0c;保证接口的正确和稳定性。因此&#xff0c;接口测试也是后端开发中的关键环节。 但我相信&#xff0c;很多朋友是懒得测试接口的&#xff0c;觉得这很麻烦。一般自己写的接口自己都不调用&#xff0c;而是…

Linux友人帐之网络编程基础邮件服务器与DHCP服务器

一、邮件服务器概述 1.1邮件服务基础 邮件服务器是一种计算机程序&#xff0c;它通过电子邮件协议接收、存储、处理和发送电子邮件。邮件服务器可以与电子邮件客户端程序&#xff08;如Outlook、Thunderbird等&#xff09;或Web邮件界面&#xff08;如Gmail、Outlook.com等&am…

C语言ZZULIOJ1149:组合三位数之二

题目描述 把1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;5&#xff0c;6&#xff0c;7&#xff0c;8&#xff0c;9&#xff0c;组成三个三位数&#xff08;每个数只能用一次&#xff09;,第二个数是第一个数的2倍&#xff0c;第三个数是第一个数的3倍&#xff0c;这三…

PyTorch:GPU的使用

在深度学习领域&#xff0c;神经网络模型训练所需的计算量巨大&#xff0c;这就对计算资源提出了高要求。为了处理这一问题&#xff0c;图形处理器&#xff08;GPU&#xff09;被引入到深度学习中&#xff0c;其并行计算能力可以极大加速神经网络的训练过程。PyTorch作为一款出…

Linux_一款好用的查看系统信息的桌面软件_包名hardinfo、软件名system profiler and Benchmark

1、安装软件 对源进行更新&#xff0c;sudo apt update 安装&#xff0c;sudo apt install hardinfo 打开&#xff0c;system profiler and Benchmark 2、查看系统信息 2.1、系统基本信息_操作系统信息、内核版本、处理器等 “Summary”汇总了一些基本信息&#xff1a; 处…

蓝桥杯第三周算法竞赛D题E题

发现更多计算机知识&#xff0c;欢迎访问Cr不是铬的个人网站 D迷宫逃脱 拿到题目一眼应该就能看出是可以用动态规划来解决。但是怎么定义dp呢? 这个题增加难度的点就在当所在位置与下一个要去的位置互质的时候&#xff0c;会消耗一把钥匙。当没有钥匙的时候就不能移动了。想…

openGauss学习笔记-125 openGauss 数据库管理-设置账本数据库-校验账本数据一致性

文章目录 openGauss学习笔记-125 openGauss 数据库管理-设置账本数据库-校验账本数据一致性125.1 前提条件125.2 背景信息125.3 操作步骤 openGauss学习笔记-125 openGauss 数据库管理-设置账本数据库-校验账本数据一致性 125.1 前提条件 数据库正常运行&#xff0c;并且对防…

2023最新软件测试20个基础面试题及答案

什么是软件测试&#xff1f; 答案&#xff1a;软件测试是指在预定的环境中运行程序&#xff0c;为了发现软件存在的错误、缺陷以及其他不符合要求的行为的过程。 软件测试的目的是什么&#xff1f; 答案&#xff1a;软件测试的主要目的是保证软件的质量&#xff0c;并尽可能大…

大数据架构Lambda-架构师(六十九)

随着信息时代技术的发展&#xff0c;数据量的快速增加逐渐飙升到了惊人的数量级别。并且数据的采集与处理技术还在更新加快。大数据中&#xff0c;结构化占比百分之15左右&#xff0c;其余百分之85都是非结构化数据&#xff0c;他们大量存在于社交网络、互联网和电子商务等领域…

TikTok运营干货——养号篇

随着国内抖音红利的进一步释放&#xff0c;越来越多人涌入了TikTok国内外市场。而TikTok作为海外新兴的社媒平台&#xff0c;也在迅速的发展着&#xff0c;吸引了大批的跨境电商玩家入驻。然而&#xff0c;TikTok运营的一大难点就是养号&#xff0c;许多人还没开始转化号就被封…

小程序action-sheet结合自定义tabbar显示

要实现此效果&#xff0c;遇到的问题&#xff1a;背景在电脑端调试的情况正常的情况下&#xff0c;手机端点击事件工单&#xff0c;返回回来的时候action-sheet卡住在屏幕上&#xff0c;点击遮罩层都不消失。更奇怪的是 这种情况并不是每次发生&#xff0c;而是有时候发生&…

【星海出品】云存储 ceph

https://ceph.com/en/ 建议运行带有两个网络的Ceph存储集群&#xff1a;公共&#xff08;前端&#xff09;网络和集群&#xff08;后端&#xff09;网络。为了支持两个网络&#xff0c;每个Ceph节点都需要有多个NIC。 Monitor 一个Ceph集群需要多个Monitor组成的小集群&#x…