【C++】异常处理 ① ( 异常概念引入 | 抛出异常语法 | 捕获异常语法 | 异常捕获流程 | 异常处理代码示例 )

文章目录

  • 一、异常处理
    • 1、异常概念引入
    • 2、抛出异常语法
    • 3、捕获异常语法
    • 4、异常捕获流程
  • 二、异常处理代码示例
    • 1、错误代码示例 - 抛出异常 / 不捕获异常
    • 2、正确代码示例 - 抛出异常 / 捕获异常
    • 3、正确代码示例 - 抛出异常 / 捕获异常不处理继续抛出异常





一、异常处理




1、异常概念引入


异常是一种 特殊的程序流控制机制 , 用于处理程序中可能出现的错误或异常情况 ;

当程序执行错误时 , 由 throw 关键字抛出异常 , 并即跳转到相应的异常处理程序中 ; 如果没有适当的异常处理程序处理该异常 , 程序会崩溃终止 ;


异常与函数对比 :

  • 函数 是一种 以 栈结构 展开的上下函数衔接的程序控制系统 ;
  • 异常 是一种 特殊的程序流控制机制 , 用于处理程序中可能出现的错误或异常情况 ; 异常 依附于栈结构 , 却可以同时设置多个 异常类型 作为 异常捕获条件 ;

异常是跨函数的 , 下图中 函数 f 调用 函数 g , 函数 g 调用 函数 h ;
在这里插入图片描述
在 函数 h 中抛出异常 , 异常会沿着函数 调用顺序 , 先抛给 函数 g , 如果 g 不处理 , 则继续向上抛给 函数 f ;

上述 异常处理 机制 , 可以在不同的函数中 进行 抛出异常 和 处理异常 的操作 ;

这样 函数设计开发时 只需要解决具体的问题 , 不需要过多考虑 异常处理 ;


2、抛出异常语法


抛出异常 语法 : 使用 throw 关键字 , 抛出异常对象 ;

throw 异常对象;

代码示例 : 在下面的函数中 , 抛出一个 int 类型的异常 ;

// 1. 在 函数 中 抛出异常
void fun(int a) {
	if (a == 0) {
		// 抛出一个 int 类型的异常
		throw 2;
	}
}

3、捕获异常语法


异常捕获 语法 : 在 try 代码块中执行 可能抛出异常的 代码 , 如果出现异常 , 就可以在 catch 分支中进行捕获 ;

try {
	// 出现异常的代码块
} catch( 异常类型声明 )

代码示例 : 下面的代码中 , 捕获 try 代码块中产生的异常 ,

  • 如果捕获到 int 类型的异常 , 则执行 catch (int e) 分支中的代码 ,
  • 如果捕获到其它类型的异常 , 则执行 catch ( … ) 分支中的代码 ;
	// 2. 捕获并处理异常
	try
	{
		// 调用可能产生异常的函数
		fun(0);
	}
	catch (int e)
	{
		cout << "捕获到异常 : " << e << endl;
	}
	catch ( ... )
	{
		// 捕获 ... 可以捕获未知其它类型的异常
		cout << "捕获到未知类型异常"<< endl;
	}

4、异常捕获流程


异常捕获流程 :

  • 抛出异常 : 如果遇到错误 , 需要抛出异常 , 可以使用 throw 关键字 , 抛出一个异常对象 , 这个异常对象可以是任意类型 , 如 int 类型 ;
  • try 代码块处理异常 : 在 try 代码块中 , 执行可能抛出异常的代码 , 上方的代码顺序执行到达 try 代码块时 , 则进入 try 代码块 继续执行其中的代码 ;
    • 正常执行 : 如果 try 保护段代码正常执行 , 没有出现异常 , 则执行完毕后继续执行 后续代码 , 最后一个 catch 分支之后的代码 ;
    • 出现异常 :
      • 捕获异常 : 如果出现了异常 , 恰好被 catch 分支捕获 , 则执行 catch 分支代码 ;
        • 处理异常 : 如果能处理该异常 , 则处理异常错误 ;
        • 继续向上抛出异常 : 如果无法处理 , 则继续向上抛出给调用者 , 让上一级函数处理 ;
      • 未捕获异常 : 如果出现了异常 , 没有被 catch 分支捕获 , 则运行 terminate 函数 , 在该函数中调用 abort 终止程序 ;




二、异常处理代码示例




1、错误代码示例 - 抛出异常 / 不捕获异常


错误代码示例 : 在下面的代码中 , 没有捕获异常 , 则在执行时会报错 : " 0x755FF932 处(位于 HelloWorld.exe 中)有未经处理的异常 " ;

#include "iostream"
using namespace std;

// 1. 在 函数 中 抛出异常
void fun(int a) {
	if (a == 0) {
		// 抛出一个 int 类型的异常
		throw 2;
	}
}

int main() {

	// 调用可能产生异常的函数
	fun(0);

	// 控制台暂停 , 按任意键继续向后执行
	system("pause");

	return 0;
};

执行结果 :

0x755FF932(位于 HelloWorld.exe 中)有未经处理的异常: 
Microsoft C++ 异常: int,位于内存位置 0x00F6FB6C 处。 

在这里插入图片描述


2、正确代码示例 - 抛出异常 / 捕获异常


异常捕获完整代码示例 :

#include "iostream"
using namespace std;

// 1. 在 函数 中 抛出异常
void fun(int a) {
	if (a == 0) {
		// 抛出一个 int 类型的异常
		throw 2;
	}
}

int main() {

	// 2. 捕获并处理异常
	try
	{
		// 调用可能产生异常的函数
		fun(0);
	}
	catch (int e)
	{
		cout << "捕获到异常 : " << e << endl;
	}
	catch ( ... )
	{
		// 捕获 ... 可以捕获未知其它类型的异常
		cout << "捕获到未知类型异常"<< endl;
	}

	// 控制台暂停 , 按任意键继续向后执行
	system("pause");

	return 0;
};

执行结果 :

捕获到异常 : 2
请按任意键继续. . .

在这里插入图片描述


3、正确代码示例 - 抛出异常 / 捕获异常不处理继续抛出异常


异常是跨函数的 , 异常会从本函数中抛给调用本函数的调用者 ( 调用函数 ) ;

  • 如 : 在 main 函数中调用 fun 函数 , 如果 fun 函数中抛出异常 , 则抛给了 main 函数 , 需要在 main 函数中捕获并处理异常 ;

在下面的示例中 , fun2 函数中捕获 fun 函数中的 异常未处理 , 抛到了 main 函数中 ;

main 函数中的异常必须处理 , 否则程序崩溃 ;


代码示例 :

#include "iostream"
using namespace std;

// 1. 在 函数 中 抛出异常
void fun(int a) {
	if (a == 0) {
		// 抛出一个 int 类型的异常
		throw 2;
	}
}

// 3. 捕获异常不处理 , 继续向上抛出
void fun2(int a) {

	try
	{
		// 执行可能抛出异常的函数
		fun(a);
	}
	catch (int e)
	{
		// 捕获到了异常, 但是不处理继续向上抛出
		throw;
	}

}

int main() {

	// 2. 捕获并处理异常
	try
	{
		// 调用可能产生异常的函数
		//fun(0);

		// 异常是跨函数的
		// 调用可能产生异常的函数
		// 该 fun2 函数中捕获 fun 函数中的 异常未处理 
		// 抛到了 main 函数中
		fun2(0);
	}
	catch (int e)
	{
		cout << "捕获到异常 : " << e << endl;
	}
	catch ( ... )
	{
		// 捕获 ... 可以捕获未知其它类型的异常
		cout << "捕获到未知类型异常"<< endl;
	}

	// 控制台暂停 , 按任意键继续向后执行
	system("pause");

	return 0;
};

执行结果 :

捕获到异常 : 2
请按任意键继续. . .

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

nodejs微信小程序+python+PHP问卷调查系统的设计与实现-计算机毕业设计推荐

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…

java源码-Java方法的定义和使用详解

1、 方法定义 如果我们想定义一个方法&#xff0c;基本语法如下&#xff1a; 修饰符&#xff1a;方法的修饰符是可选的&#xff0c;用于定义该方法的访问类型&#xff0c;可用的修饰符包括public/private/protected/默认的。 返回值&#xff1a;方法可以有返回值&#xff0c;…

《Junit单元测试》

目录 SpringBoot2.2.0版本之前的单元测试模式 SpringBoot2.2.0版本之后的单元测试模式 SpringBoot2.4以上版本移除了默认对Vintage的依赖 SpringBoot2.2.0版本之前的单元测试模式 SpringBooot 2.2.0 版本开始引入Junit5作为单元测试默认库&#xff0c;之前的版本是使用Junit…

[二分查找双指针]LeetCode881: 救生艇

作者推荐 [二分查找]LeetCode2040:两个有序数组的第 K 小乘积 本文涉及的基础知识点 二分查找算法合集 题目 给定数组 people 。people[i]表示第 i 个人的体重 &#xff0c;船的数量不限&#xff0c;每艘船可以承载的最大重量为 limit。 每艘船最多可同时载两人&#xff0…

Ubuntu系统配置深度学习环境之nvidia显卡驱动和cuda安装

前言 NVIDIA 显卡驱动是为了确保 NVIDIA 显卡能够正确运行而开发的软件。显卡驱动负责与操作系统通信&#xff0c;管理显卡的各种功能&#xff0c;并提供性能优化和兼容性保证。安装适用于特定显卡型号和操作系统版本的最新驱动程序是确保显卡能够正常工作的重要步骤。 CUDA 是…

如何缓解可观察性挑战?

可观察性正在成为当代 DevOps 实践的基石。即使传统上不属于 DevOps 的部门也看到了在可观察性团队的支持下带来的好处。然而&#xff0c;到 2023 年&#xff0c;组织发现采用之路比预期更加崎岖。以下是 DevOps 团队在可观察性方面面临的七个最大挑战以及一些缓解这些挑战的建…

严蔚敏数据结构题集 p18(2.25——2.30)(c语言代码实现)

目录 2.25假设以两个元素依值递增有序排列的线性表A和B分别表示两个集合(即同一表中的元素值各不相同),现要求另辟空间构成一个线性表C,其元素为A和B中元素的交集,且表C中的元素也依值递增有序排列。试对顺序表编写求C的算法。 2.26要求同2.25题。是对单链表编写求C的算法 2.…

Linux socket编程(9):IO复用之poll和epoll详解

在之前的文章中&#xff0c;我们学习了IO复用模型之select原理及例子&#xff0c;但是select有监听描述符个数的限制&#xff0c;而且select的效率并不高&#xff0c;所以这篇文章就来学习效率更高的poll和Linux特有的epoll方法。 文章目录 1 select/poll/epoll对比2 poll2.1 p…

【开源项目】Windows串口通信组件 -- Com.Gitusme.IO.Ports.SerialPort

目录 1、项目介绍 2、组件集成 1&#xff09;下载地址&#xff1a; 2&#xff09;添加项目依赖 3、使用方法 4、GitHub项目地址 1、项目介绍 Com.Gitusme.IO.Ports.SerialPort 是一款 Windows 串口通信组件&#xff0c;基于.Net Core 3.1 开发&#xff0c;支持 Console、Wi…

PostgreSQL有意思的现象:支持不带列的表

1、前言 以前从没有试过建一张表&#xff0c;不带任何列。在PG中却支持这种语法。这是个什么鬼? 最近&#xff0c;把PG源码扒了下&#xff0c;简单浏览了下最近的一些merge。其中有一个fix&#xff1a; eeb0ebad79 ("Fix the initial sync tables with no columns.&qu…

CRM简单小结

思想 对于三层架构&#xff0c;一个模块对应一个controller&#xff0c;controller实际就是Servlet&#xff1b;一张表对应一个domain类对应一个dao接口对应一个mapper文件&#xff1b;service层没有严格规定&#xff0c;如果两张表内容相近&#xff0c;用一个service接口也可以…

【C++练级之路】【Lv.2】类和对象(上)(类的定义,访问限定符,类的作用域,类的实例化,类的对象大小,this指针)

目录 一、面向过程和面向对象初步认识二、类的引入三、类的定义四、类的访问限定符及封装4.1 访问限定符4.2 封装 五、类的作用域六、类的实例化七、类的对象大小的计算7.1 类对象的存储方式猜测7.2 如何计算类对象的大小 八、类成员函数的this指针8.1 this指针的引出8.2 this指…

排序算法介绍(二)冒泡排序

0. 简介 冒泡排序&#xff08;Bubble Sort&#xff09;是一种简单的排序算法。它重复地遍历要排序的数列&#xff0c;一次比较两个元素&#xff0c;如果他们的顺序错误就把他们交换过来。遍历数列的工作是重复地进行直到没有再需要交换&#xff0c;也就是说该数列已经排…

CentOS7搭建部署NTP服务器

服务端配置&#xff1a; yum install ntp ntpdate -y #下载安装包 修改配置文件&#xff0c;同步阿里的NTP服务器 vim /etc/ntp.conf systemctl start ntpd #启动该服务 ntpq -p #查看是否同步了阿里的NTP 服务端同步成功后&#xff0c;可以去新增…

移除元素、合并两个有序数组(leetcode)

一、移除元素 思路三&#xff1a; while(src<numsSize) 使用一个 while 循环来遍历数组。循环的条件是 src 必须小于 numsSize&#xff0c;以确保不会越界。 if(nums[src]!val) 如果当前 src 指向的元素不等于给定的值 val&#xff0c;则执行以下操作&#xff1a; nums[ds…

国际语音通知系统有哪些优点?国际语音通知系统有哪些应用场景?

国际语音通知是一种全球性的通信工具&#xff0c;它通过语音方式向用户发送各种重要信息和提示。无论是快递到货的取件提醒、机场航班的延误通知&#xff0c;还是银行账户的余额提醒&#xff0c;国际语音通知都能准确、迅速地将信息传达给用户。 三、国际语音通知系统有哪些优…

Jupyter NoteBook未授权访问漏洞

任务一&#xff1a; 复现未授权访问的漏洞 任务二&#xff1a; 利用Jupter Notebook控制台执行系统命令&#xff0c;读取/etc/passwd内容 1.搭建环境 2.new下面直接进入终端&#xff0c;而且也不需要登录&#xff0c;我就直接进入了管理界面 3.直接把指令输入进入&#xf…

【Unity动画】为一个动画片段添加事件Events

动画不管播放到那一帧&#xff0c;我们都可以在这里“埋伏”一个事件&#xff08;调用一个函数并且给函数传递一个参数&#xff0c;参数在外部设置&#xff0c;甚至传递一个物体&#xff09;&#xff01; 嗨&#xff0c;亲爱的Unity小伙伴们&#xff01;你是否曾想过为你的动画…

Java 数组另类用法(字符来当数组下标使用)

一、原因 看力扣的时候发现有位大佬使用字符来当数组下标使用。 class Solution {public int lengthOfLongestSubstring(String s) {int result 0;int[] hash new int[130];int i 0;for(int j 0; j < s.length(); j) {while(hash[s.charAt(j)] > 0) {hash[s.charAt…

基于SSM框架开发的酒店后台管理系统

基于SSM框架开发的酒店后台管理系统 文章目录 基于SSM框架开发的酒店后台管理系统 一.引言二.系统设计三.技术架构四.功能实现五.界面展示六.源码获取 一.引言 酒店管理系统是一个集客房预订、前台管理、客户服务、财务管理等功能于一体的综合性软件系统。它能够帮助酒店高效地…