C++——异常

作者:几冬雪来

时间:2023年11月21日

内容:C++板块异常讲解

目录

前言:

异常: 

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

捕获异常:

异常的相关特性:

string与抛异常:

catch(...):

类型匹配:

常用的抛异常:

异常规范: 

异常的优缺点: 

优点:

缺点:

总结: 

结尾:


前言:

在上一篇博客中我们讲解了C++的重要知识点——map与set,map和set可谓是C++一大必须学习的知识点,那么在消化之前,我们来讲解C++中的异常。 

异常: 

在学习无论是C语言又或者C++,只要是编程语言那就肯定存在出错的情况,而编译器在代码出错的时候就会产生异常

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

首先我们先来说C语言处理错误的方式。

第一个方式就是终止程序,类似断言或者退出函数等等行为。、

下一个则是返回错误码,这是C语言常见的处理错误的方式,但是它也会存在一些问题。比如我们无法得知代码在哪个模块出事的

捕获异常:

就像是错题要找出来错在哪里一样,既然在编程的时候发现了异常,那么我们就应该将异常给捕获住

捕获异常就需要对应的代码去进行该操作

在进行捕获异常的时候就需要用到这里的代码就需要使用到这里的try...catch()

try...catch()就是用来捕获异常的,接下来通过一组代码来了解一下捕获异常。

这个地方发生异常的地方可能是在Func函数中,也可能是在Func函数的下一层出现了异常的问题

如果这个地方发生了除0失误的话,这里结果就会抛异常,然后再将其捕获最后将其输出

这发生的除0失误,导致程序终止了,这里就将Dibision函数中的抛异常的语句输出出来,如果输入的两个值没有发生除0失误的话就正常的执行,返回,输出结果

然后就是try...catch语句中的catch语句

一般情况下程序是不会去执行catch的代码,只有一种情况会执行,那就是抛异常之后,程序会直接跳到catch的地方去,这也是抛异常的优势所在。 

如果是以前我们的代码在太深处发生错误的话,这个地方只能一层一层的返回然后判断在重复以上操作

但是抛异常并不是是这样做,哪怕函数有多深,只要检查到了异常,它会直接跳转到catch处函数栈帧也会依次销毁,这就是catch的一大优势所在

异常的相关特性:

在了解了一定程度的异常后,这个我们来看一下异常的相关特性

首先第一条,异常是通过抛出对象引发的。  

然后代码在throw的时候会异常,而代码在报错的时候会执行throw,throw的后面不止能跟字符串对象,C++规则在这个地方我们可以抛任意类型的对象

也就是可以throw任意类型的对象

同时捕获的时候也有类型,如果catch的类型与throw的类型不匹配是捕获不到的

但是如果代码抛异常了,却没有被成功的捕获的话,这种情况下编译器就会发生报错

而且没有捕获的情况有很多

上边就是没有捕获可能会发生的原因。

C++规定异常必须被捕获,如果没能完成异常的捕获,这个地方我们的编译器就会弹框报错,程序直接终止。 

如果成功捕获异常后,它会沿着catch的子句继续往后执行

就类似这里,即使这个地方抛异常了,下面的输出“xxx”的指令依旧会执行

接下来还有一个重要的点,如果在程序执行的中间将异常捕获成功的话,这个地方就只需要跳转到离它近的catch即可,而catch只用执行一次即可

string与抛异常:

再然后就是string与抛异常之间的关系

在讲解抛异常的时候我们有说过throw的类型是没有限制的,那么这个地方就有人提出了问题。既然类型没有限制,那么它的类型能不能更改为string类型

众所周知string在离开作用域的时候会调用虚构,而throw是一口气跳转到第一个catch处

这里是可以正常抛一个string的异常出来, 因为在抛异常的原则中又说,抛异常和返回值很像,它会进行拷贝,类似传值返回

这个拷贝的对象在被捕获之后才被销毁

catch(...):

再然后讲解一下catch处的问题

在上文中有提及throw的类型可以是整形,可以是浮点型,甚至能是string型。那么相对应的,在catch接收处的类型会不会出现问题呢

这个地方为了防止有人一不小心抛了异常又没有将其捕获,异常的捕获机制给了这样的一种方式——catch(...)

这里的catch(...)中的省略号表示它可以捕获任意类型的异常

但是这种方式有一个缺陷,那就是我们无法检测出是什么错误,因此我们将这个错误称为未知异常,它用来捕获一些不规范的异常

并且catch(...)的抛异常一般都是放在最后一个位置处,作为编译器的最后一道防线,前面都走完了到最后进行捕获

这也就意味着有人没有按规范书写代码

并且捕获异常的位置通常都比较统一,有些情况捕获的异常还需要进行处理

类型匹配:

在上文中,我们有提到了过catch的类型要与throw的类型相匹配,这样才能成功返回

但是实际中抛出和捕获的匹配原则有一个例外,这个地方我们可以抛出的派生类对象,使用基类进行捕获

而这里基于上面的情况就出现了一种异常体系。 

常用的抛异常:

再接下来就来谈一谈我们经常用到的抛异常

在这张表中我们重点要关注的是exception,bad_alloc与out_of_range这三个异常

其中exception是所以标志C++异常的父类,其他的异常可以认为是exception的派生类对象bad_alloc就是抛new的异常,最后一个out_of_range则是用量抛vector等的异常,如果它们越界那就抛异常

平时主要还是使用exception来抛异常

就如同上图就是我们new抛异常的代码书写,就是使用到了bad_alloc

异常规范: 

在基本了解为空异常的内容和操作之后接下来我们来讲解异常的一些规范

而在之前的书写异常的过程中就有有关异常规范的代码

例如在new进行抛异常的时候,在它的函数后面会加上这一串的代码

这里的两串代码都被称为异常规范

异常规范出现的原因是因为异常代码执行的时候会出现一个问题,这个问题会引起值停留乱跳,即使打断点都断不住

在上图下边的代码表示,如果不抛异常就用throw(),如果要抛异常类似上图的这串代码就表示会抛bad_alloc的异常

如果带抛异常的时候我们要求抛多个类的异常的话可以在函数后面写上throw与要抛异常的类,它们之间要用“,”隔开。 

但是这种行为并不是强制的,因为C++兼容C语言,而C语言中没有这套规范。 

而因为它不是强制的,所以只有极少数人使用它。

在这种情况下我们搞清楚抛哪几种异常,则是非常麻烦的一件事情

因此在C++11中对这种行为进行了简化

如果确定不抛异常就在函数的后面书写上一个noexcept,如果我们会抛异常但是不知道抛什么异常的话,这里就什么都不写

但是也有例外,那就是析构函数没有保证抛不抛异常。 

这里简化的规则是——标记出不抛异常的函数

异常的优缺点: 

在讲解完了异常之后,临近结束时我们来讲解一下异常的优缺点

优点:

这里异常的第一个有用的点就是可以清晰准确的展示出各种错误信息,可以更好的定位程序的错误。  

再则如果深层函数发生了错误,异常不需要一层一层返回。

第三点,很多第三方库都包含异常。

以上都是异常的优点。

缺点:

接下来讲解一下异常的缺点。

首先就是执行流乱跳问题,这会使代码非常的混乱。

第二点就是异常会有一定程度上的性能的开销。

然后就是C++没有垃圾回收机制,有异常后任意导致内存泄漏,死锁等安全问题。

这里异常规范不是强制性。 

总结: 

但是总体来说,异常的利大于弊 ,在OO的语言(面向对象)会经常使用到。

代码:

#include<iostream>
#include<string> 
using namespace std;

//double Division(int a, int b)
//{
//	if (b == 0)
//	{
//		throw "Division by zero condition!";
//	}
//	else
//	{
//		return ((double)a / (double)b);
//	}
//}
//
//void Func()
//{
//	try
//	{
//		int len;
//		int time;
//		cin >> len >> time;
//		cout << Division(len, time) << endl;
//
//	}
//	catch (const char* errmsg)
//	{
//		cout << errmsg << endl;
//	}
//}
//
//int main()
//{
//	try
//	{
//		Func();
//	}
//	catch (const char* errmsg)
//	{
//		cout << errmsg << endl;
//	}
//	cout << "xxx" << endl;
//	return 0;
//}

//double Division(int a, int b)
//{
//	if (b == 0)
//	{
//		string s ("Division by zero condition!");
//		throw s;
//	}
//	else
//	{
//		return ((double)a / (double)b);
//	}
//}
//
//void Func()
//{
//		int len;
//		int time;
//		cin >> len >> time;
//		cout << Division(len, time) << endl;
//}
//
//int main()
//{
//	try
//	{
//		Func();
//	}
//	catch (const char* errmsg)
//	{
//		cout << errmsg << endl;
//	}
//	catch (...)
//	{
//		cout << "未知异常" << endl;
//	}
//	cout << "xxx" << endl;
//	return 0;
//}

class Exception
{
public:
	Exception(const string& errmsg, int id)
		:_errmsg(errmsg),
		_id(id)
	{

	 }

	virtual string what()const
	{ 
		return _errmsg;
	}

protected:
	string _errmsg;
	int _id;
};

class SqlException :public Exception
{
public:
	SqlException(const string& errmsg, int id, const string& sql)
		:Exception(errmsg, id),
		_sql(sql)
	{

	}

	virtual string what()const
	{
		string str = "SqlException:";
		str += _errmsg;
		str += "->";
		str += _sql;

		return str;
	}

private:
	const string _sql;
};

class CacheException :public Exception
{
public:
	CacheException(const string& errmsg, int id)
		:Exception(errmsg,id)
	{

	}
	virtual string what()const
	{
		string str = "CacheException:";
		str += _errmsg;
		return str;
	}
};

class HttpServerException :public Exception
{
public:
	HttpServerException(const string& errmsg, int id, const string& type)
		:Exception(errmsg,id),
		_type(type)
	{

	}
	virtual string what()const
	{
		string str = "HttpServerException:";
		str += _type;
		str += ":";
		str += _errmsg;

		return str;
	}
private:
	const string _type;
};

结尾:

到这里我们的异常部分的知识就要暂告一段落了,但是这并不意味着C++里面异常的知识就此结束了,这个我们提到了异常可能发生执行流乱跳的问题,而且这个问题将在后面的智能指针处得到优化,只不过那都是以后的事情了,最后希望这篇博客能给各位带来帮助。

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

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

相关文章

Monoxide relay机制和连弩挖矿

这篇文章就两个点&#xff0c;relay机制 、 连弩挖矿 relay 最终原子性 Eventual Atomicity 一笔跨链交易&#xff0c;从取款shard中发出&#xff0c;到存款shard中. 当收款shard中将这笔夸片交易打包上链后&#xff0c;原子性才执行结束。 这样做的延迟是比较小的。 如何应…

基于单片机的空气质量实时监测系统(论文+源码)

1. 系统设计 通过文献和市场调查&#xff0c;本设计的实现方案框架是以单片机为核心控制处理器搭建外围的功能模块如温度传感器模块、湿度传感器检测模块、二氧化碳传感器检测设备模块、无线通信模块和蜂鸣器声光报警提示模块来实现&#xff0c;辅以显示模块来展示。 该系统通…

什么是神经网络(Neural Network,NN)

1 定义 神经网络是一种模拟人类大脑工作方式的计算模型&#xff0c;它是深度学习和机器学习领域的基础。神经网络由大量的节点&#xff08;或称为“神经元”&#xff09;组成&#xff0c;这些节点在网络中相互连接&#xff0c;可以处理复杂的数据输入&#xff0c;执行各种任务…

Find My自行车|苹果Find My技术与自行车结合,智能防丢,全球定位

自行车&#xff0c;这项古老而简单的交通工具&#xff0c;近年来在中国经历了一场令人瞩目的复兴。从城市的街头巷尾到乡村的田园小路&#xff0c;自行车成了一种新的生活方式&#xff0c;一个绿色出行的选择。中国的自行车保有量超过两亿辆&#xff0c;但是自行车丢失事件还是…

为什么需要MuleSoft?如何与Salesforce协同工作?

MuleSoft通过一个集成平台将应用程序及其数据(跨云和内部云)连接起来。这被称为iPaaS&#xff0c;可将云应用程序相互集成&#xff0c;以及与本地和传统应用程序集成。 MuleSoft非常适合希望过渡到云的组织&#xff0c;提供了一种强大的集成解决方案。随着组织越来越依赖云及其…

赞评论收藏分享格雷希尔用于机器手抓取的G80P系列自动化螺纹快速接头的应用领域

格雷希尔GripSeal快速密封连接器针对螺纹孔的快速密封有二种操作方式&#xff0c;手动操作和气压驱动;但随着科技的不断发展&#xff0c;机器手越来越多的代替人工在工位上操作&#xff0c;于是我们又研发出适用于机器手抓取的G80P系列自动化螺纹快速连接器&#xff0c;使用机器…

「MobileNet V3」70 个犬种的图片分类

✅作者简介&#xff1a;人工智能专业本科在读&#xff0c;喜欢计算机与编程&#xff0c;写博客记录自己的学习历程。 &#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&…

C 语言获取文件绝对路径

示例代码 1&#xff0c;不包含根目录绝对路径&#xff1a; #include <stdlib.h> #include <stdio.h>int main(void) {char *fileName "/Dev/test.txt";char *abs_path _fullpath(NULL, fileName, 0);printf("The absolute path is: %s\n", a…

【JavaEE初阶】 JavaScript基础语法——贰

文章目录 &#x1f332;条件语句&#x1f6a9;if 语句&#x1f6a9;三元表达式&#x1f6a9;switch&#x1f6a9;循环语句&#x1f388;while 循环&#x1f388;continue&#x1f388;break&#x1f388;for 循环 &#x1f340;数组&#x1f6a9;创建数组&#x1f6a9;获取数组…

2014年2月24日 Go生态洞察:FOSDEM 2014上的Go演讲精选

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

【教程】cpp转python Nanobind 实践 加速轻量版 pythonbind11

主要是尝试一下把c这边的函数封装打包给python用&#xff0c;选择nanobind的原因是&#xff1a;1. 优化速度快&#xff0c;2. 生成二进制包小&#xff0c;不过pythonbind11是更为广泛知道的&#xff0c;nanobind也是pythonbind11作者后续做的&#xff0c;可以查看作者写的 why …

多项式求和

题目描述 给定程序中 fun 函数的功能是&#xff1a;求出以下分数序列的前 n 项之和&#xff0c;并通过函数值返回 main 函数。 输入格式 输入参数。 输出格式 计算公式返回的结果。 输入输出样例 输入1 5 输出1 8.391667 python解&#xff1a; def fun(n):a1b2s0for…

【数据结构】HashMap 和 HashSet

目录 1.哈希表概念 2冲突 2.1概念 2.2 冲突-避免 2.3冲突-避免-哈希函数设计 2.4 冲突-避免-负载因子调节 ​编辑 2.5 冲突-解决-开散列/哈希桶 2.5冲突严重时的解决办法 3.实现 4.性能分析 5.与Java集合类的关系 1.哈希表概念 在顺序结构中&#xff0c;元素关键码和存…

风电场数字孪生-升压站BIM三维模型-obj格式

简介&#xff1a; 风电场中的升压站三维模型&#xff0c;obj格式&#xff0c;采用BIM技术建模&#xff0c;可应用于风电场三维数字孪生领域&#xff0c;用于对升压站进行漫游浏览&#xff1b;三维可视化场景应用&#xff1b;风电场三维设计模型。 下载地址 风电场数字孪生-升…

2019ICPC南京站

A A Hard Problem 题意&#xff1a;给定一个正整数 n &#xff0c;你需要找出最小整数 k&#xff0c;满足&#xff1a;从{1,2,⋯,n}中任意选择长度为k的子集&#xff0c;存在两个不同的整数 u,v∈T, 且 u 是 v 的因数。 思路&#xff1a;打表找规律 #include <bits/std…

微服务实战系列之加密RSA

前言 在这个时代&#xff0c;我们选择的人生目标已丰富多彩&#xff0c;秉持的人生态度也千差万别&#xff1a; 除了吃喝玩乐&#xff0c;还有科技探索&#xff1b; 除了CityWalk&#xff0c;还有“BookWalk”&#xff1b; 除了走遍中国&#xff0c;还有走遍世界&#xff1b; …

源码安装Apache

一、下载Apache,源码安装Apache #下载 [rootlocalhost opt]# wget -c https://mirrors.aliyun.com/apache/httpd/httpd-2.4.58.tar.gz [rootlocalhost opt]# ls httpd-2.4.58.tar.gz [rootlocalhost opt]# tar -xf httpd-2.4.58.tar.gz [rootlocalhost opt]# ls httpd-2.4.58…

怎么让NetCore接口支持Json参数

项目&#xff1a;NetCore Web API 接口支持Json参数需要安装Newtonsoft.Json.Linq和Microsoft.AspNetCore.Mvc.NewtonsoftJson Program代码 //支持json需要安装Microsoft.AspNetCore.Mvc.NewtonsoftJson using Newtonsoft.Json.Serialization;var builder WebApplication.Cr…

机器学习8:在病马数据集上进行算法比较(ROC曲线与AUC)

ROC曲线与AUC。使用不同的迭代次数&#xff08;基模型数量&#xff09;进行 Adaboost 模型训练&#xff0c;并记录每个模型的真阳性率和假阳性率&#xff0c;并绘制每个模型对应的 ROC 曲线&#xff0c;比较模型性能&#xff0c;输出 AUC 值最高的模型的迭代次数和 ROC 曲线。 …

力扣1038. 从二叉搜索树到更大和树(java,树的中序遍历解法)

Problem: 1038. 从二叉搜索树到更大和树 文章目录 题目描述思路解题方法复杂度Code 题目描述 给定一个二叉搜索树 root (BST)&#xff0c;请将它的每个节点的值替换成树中大于或者等于该节点值的所有节点值之和。 提醒一下&#xff0c; 二叉搜索树 满足下列约束条件&#xff…