【C++】异常

文章目录

  • 1. C语言传统的处理错误的方式
  • 2. C++异常
    • 概念
    • 用法
    • 异常的抛出和匹配原则
      • 规则1
      • 情况2
        • 抛出异常位置最近的验证
        • 对象类型匹配的验证
      • 规则3
      • 规则4
    • 异常的重新抛出
    • 异常规范

1. C语言传统的处理错误的方式

错误处理机制:
1.终止程序
如:assert 断言终止 ,会直接报告出现错误的位置
(assert只在debug版本生效)

如:发生内存错误,或者除0错误时,导致终止程序


2. 返回错误码
错误码本质就是一个编号,不能包含更多的信息,就需要程序员自己去查对应的错误信息,很不方便
所以为了在产生错误时,有更丰富的信息显示, C++就提出了异常

异常 可以抛一个对象出来,对象可以包含各种各样的信息

2. C++异常

概念

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

用法

分为抛出异常 (throw)和 捕获异常(try catch)

throw:出现问题时,使用 thow关键字 进行 抛异常
catch : 在想要处理问题的地方, 通过 异常处理程序 捕获异常, catch 关键字用于 捕获异常
try :try块中代码块标识将被激活的特定异常,后面通常跟 catch块


抛异常,异常必须被捕获 ,若没有被捕获就会报错

该图程序中只有抛异常,没有捕获异常存在,所以当b为0时,程序直接报错


抛异常和捕获的位置可以有很多个地方

当发现错误时,一般是由最外层处理
如:上图程序中先由main 函数调用Func,再由Func函数调用 Division,在Division中完成抛异常
所以应在最外层的main函数中捕获异常


异常的抛出和匹配原则

规则1

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

catch时,需要跟throw抛出对象类型 进行匹配
如:此时的throw传过来的是字符串,所以catch 用const char*接收

由于有捕获异常,所以当再次b为0时,就不会报错了,显示的详细信息为Division by zero condition!

try和catch 两者是配对的, catch 只能捕获 try里面的抛的异常
如:在主函数中的catch 捕获异常只能 捕获 Func函数中抛的异常


情况2

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

抛出异常位置最近的验证

若在Func函数处添加捕获,并且类型与对象类型匹配
则当b为0时,由于Func函数处 更近,所以在Func函数处捕捉异常,而不在main函数中捕获异常


对象类型匹配的验证

此时Func函数中的捕获异常与对象类型不匹配,当再次输入b为0时,在main函数处 捕获异常

规则3

若Func函数和main函数的捕获异常 与对象类型都不匹配 ,则程序会报错


此时由于两个捕获异常都与对象类型不匹配,所以进入catch(…)中

使用catch(…),若有匹配的就用匹配的,若没有匹配的,就使用catch(…),对任意类型异常进行捕获
防止一些异常没有捕获(没有对象类型匹配),导致程序终止


规则4

抛出异常对象后,会生成一个异常对象的拷贝,因为抛出的异常对象可能是一个临时对象,
所以会生成一个拷贝对象,这个拷贝的临时对象会在被catch以后销毁。(这里的处理类似
于函数的传值返回)


如果错误信息只是一个字符串,有些过于简单,所以设置一个类,内部包含错误码和错误描述

由于成员变量是私有的,在类外可能拿不到,所以设置两个函数,通过函数返回值的方式取到错误码和错误描述

由于对象类型为 const Exception,所以想要使用对象取到这两个函数 ,就需要在外部加上const 修饰


对比上面,将字符串替换成了对象,对象含有错误码和错误描述两部分
通过抛异常的方式将对象 传递给 catch的捕获
在将对象的错误码和错误信息打印出来

抛异常时,并不是把e1直接传给 e
因为e1是一个局部对象,出了作用域就销毁了,会产生一个临时对象,将e1对象的错误码和错误描述拷贝给临时对象
再通过临时对象 传给 对象e,在catch结束后,临时对象销毁

异常的重新抛出

若抛异常,则会导致内存泄漏(没有使用delete释放)


若要求在main函数将异常处理, 所以可以采用异常的重新抛出
当在Func函数中的catch要捕获异常时,再将异常抛出,使main函数中进行 捕获异常

异常规范

在C++98中
exception() throw();
后面加了个throw,意思为声明这个函数不会抛异常


声明可以不给,但是加上会让人更容易理解
这个函数异常声明并不是强制的,并且比较繁琐,就导致很多人不遵循这个规范


在C++11中
若一个函数明确不抛异常的话,就加 noexcept
可能会抛异常,就什么都不加

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

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

相关文章

TX Text Control .NET for WPF 31.SP3 Crack

.NET WPF 应用程序的文档处理 将文档编辑、创建和 PDF 生成添加到您的 WPF 应用程序中。 视窗用户界面 功能齐全的文档编辑器 TX Text Control 是一款免版税、完全可编程的丰富编辑控件,它在专为 Visual Studio 设计的可重用组件中为开发人员提供了广泛的文字处理功…

[每日一水] Latex Tikz foreach 循环嵌套

\documentclass{article} \usepackage{tikz} \begin{document} \begin{tikzpicture} \foreach[count\i] \x in {20,18,...,2}\foreach[count\j] \y in {20,18,...,2}\node at (\i,\j) {\x \y}; \end{tikzpicture} \end{document}\node at (\i,\j) {\x \y}; 就是写文本的意思

Day.1 LeetCode刷题练习(最长公共前缀 C/C++两种解法)

题目: 例子: 分析题目: 主要目的:求出各个字符串的公共前缀 思路(本人解法): 用所给实例来看,不难看出我们可以直接以竖着对应来查看是否是公共前缀 , 这样就有了一…

【Python爬虫与数据分析】文件读写

目录 一、概述 二、txt文件读写 三、csv文件读写 四、Json文件读写 一、概述 读写模式: r:读数据w:覆盖写入a:追加写入rb:以二进制形式读出wb:以二进制形式写入ab:以二进制形式追加r、w、…

TypeScript 总结

文章目录 TypeScript 总结概述运行ts文件方式一方式二 基础声明变量类型数组元组联合类型取值限制 枚举类型any & unknownvoid & undefined类型适配 面向对象函数普通函数箭头函数可选参数默认参数 对象创建对象对象的类型限制 类和接口泛型简单使用多个泛型默认泛型类…

C语言经典案例-2

今天继续给大家分享C语言学习的经典练手案例 记录在校学习第三天,继续加油 今日案例来源:csdn社区每日一练 1.商品优惠计算机 商品优惠计算器 使用if语句编程实现输入购货金额,输出实际付款金额。购货折扣率如下: 购货金额≤500元…

obs录制功能源码分析

录制按钮 界面文件: 主界面:OBSBasic.ui 中开始录制按钮的objectName 是 recordButton 槽函数: void OBSBasic::on_recordButton_clicked() {//1 输出模式是否被激活if (outputHandler->RecordingActive()) {bool confirm config_get_bool(GetGlo…

LiDAR SLAM 闭环——BoW3D: Bag of Words for Real-time Loop Closing in 3D LiDAR SLAM

先说总结 现算法已经开源,代码链接: GitHub - YungeCui/BoW3D: [RA-L] BoW3D: Bag of Words for Real-Time Loop Closing in 3D LiDAR SLAM. 背景 SLAM(同时定位与地图构建)是一种让机器人在构建环境地图的同时,定位…

Spring整合Junit单元测试

1.Spring整合Junit单元测试 1.1 原始Junit测试Spring的问题 在测试类中,每个测试方法都有以下两行代码: ApplicationContext ac new ClassPathXmlApplicationContext("application.xml");BookDao bookDao (BookDao)ac.getBean("bookDa…

Angular 调试 —— 一个真实的多重循环导致的Bug

导致性能问题的原因可能很复杂&#xff0c;也可能很简单&#xff0c;今天让我们来看一个现实的例子。一个多重循环导致列表卡死。 startDemo() {this.processing true// 创建复杂数据结构const data [];for (let i 0; i < 5000; i) {const innerArray [];for (let j …

(小程序)uniapp调接口完整流程

(小程序)uniapp调接口完整流程 代码&#xff1a; <script lang"ts" setup>import { ref } from "vue"; const form ref({searchVal: "", });//搜索const searchClick () > {console.log(form.value.searchVal)let data {text: form…

git merge 和git rebase的区别

文章目录 1. 概念2. git merge2.1. 示例 3. git rebase3.1. 示例 4. 总结 1. 概念 在Git版本控制系统中&#xff0c;有两种方式可以将一个分支的更改合并到另一个分支&#xff1a;git merge 和 git rebase。虽然它们都可以完成相同的任务&#xff0c;但它们的实现方式有所不同…