C++异常介绍

news2025/1/11 12:49:20

目录

一.异常

1.1C++异常概念

1.2异常的使用

1.3异常和栈帧,重新抛出

二.异常体系

2.1自定义异常体系

 2.2C++标准库的异常体系

2.3异常规范

3.异常的优缺点

3.1优点

 3.2缺点


一.异常

1.1C++异常概念

语言传统的处理错误的方式:
1. 终止程序,如 assert ,缺陷:用户难以接受。如发生内存错误,除 0 错误时就会终止程序。
2. 返回错误码
异常是一种处理错误的方式, 当一个函数发现自己无法处理的错误时就可以抛出异常,让函数的
直接或间接的调用者处理这个错误
throw: 当问题出现时,程序会抛出一个异常。这是通过使用 throw 关键字来完成的。
catch: 在您想要处理问题的地方,通过异常处理程序捕获异常 . catch 关键字用于捕获异
常,可以有多个 catch 进行捕获。
try: try 块中的代码标识将被激活的特定异常 , 它后面通常跟着一个或多个 catch 块。

1.2异常的使用

异常的抛出和匹配原则
1. 异常是通过 抛出对象而引发 的,该 对象的类型 决定了应该激活哪个 catch 的处理代码。
2. 选中的处理代码是调用链中与该对象类型匹配且离抛出异常位置最近的那一个。
3. 抛出异常对象后,会生成一个异常对象的拷贝,因为抛出的异常对象可能是一个临时对象,
所以会生成一个拷贝对象,这个拷贝的临时对象会在被 catch 以后销毁。(这里的处理类似
于函数的传值返回)
4. catch(...) 可以捕获任意类型的异常,问题是不知道异常错误是什么。
例如:
double Division(int a, int b)
{
    // 当b == 0时抛出异常
    if (b == 0)
        throw "Division by zero condition!";
    else
        return ((double)a / (double)b);
}
void Func()
{
    int a, b;
    cin >> a >> b;
    cout << Division(a,b) << endl;
}
int main()
{
    try
    {
        Func();
    }
    catch (const char* errmsg)
    {
        cout << errmsg << endl;
    }
    catch (...)
    {
        cout << "unkown exception" << endl;
    }
    return 0;
}

当发生除零错误时会被抛出,被catch捕获,catch(...)可以捕获任意类型的异常,但会优先去匹配最适合的。

1.3异常和栈帧,重新抛出

如图

 也就是要去匹配最适合的catch语句。

有可能单个的catch不能完全处理一个异常,在进行一些校正处理以后,希望再交给更外层的调用 链函数来处理,catch则可以通过重新抛出将异常传递给更上层的函数进行处理。

例如:(例子不是很恰当)

double Division(int a, int b)
{
    // 当b == 0时抛出异常
    if (b == 0)
        throw "Division by zero condition!";
    else
        return ((double)a / (double)b);
}
void Func()
{
    int a, b;
    cin >> a >> b;
    cout << Division(a,b) << endl;
}
void show()
{
    int* arr = new int[10];
    Func();
    delete[] arr;
}
int main()
{
    try
    {
        show();
    }
    catch (const char* errmsg)
    {
        cout << errmsg << endl;
    }
    catch (...)
    {
        cout << "unkown exception" << endl;
    }
    return 0;
}

当发生除零错误时,通过throw直接跳到catch语句后,往后执行,而show()函数内new 出来的空间未释放。

解决办法:

void show()
{
    int* arr = new int[10];
    try {
        Func();//若Func函数出现异常,将前面的arr释放
   }
    catch (...)
    {
        delete[]arr;
        throw;    //重新抛出
    }
    delete[] arr;
}

二.异常体系

2.1自定义异常体系

可以定义一套继承的规范异常体系,抛出继承的派生类,捕获一个基类即可。

例如:

定义一个父类,两个子类。发生异常,抛出子类,在子类中填充错误信息,用父类接受,通过多态实现,打印错误信息。

class A
{
public:
	A(const string str, int id)
		:str_(str)
		,id_(id)
	{}
	virtual string what() const
	{
		return str_;
	}
	string str_;
	int id_;
};

class Aa : public A
{
public:
	Aa(string str,int id,string stra)
		:stra_(stra)
		,A(str,id)
	{}
	virtual string what() const
	{
		string Str("Aa");
		Str += stra_;
		return Str;
	}
private:
	string stra_;
};

class Ab :public A
{
public:
	Ab(string str, int id, string strb)
		:strb_(strb)
		,A(str,id)
	{}
	virtual string what() const
	{
		string Str("Ab");
		Str += strb_;
		return Str;
	}
private:
	string strb_;
};

void AAA()
{
	//若发生错误
	throw Aa("AAA", 8, "AAAA");
}

void BBB()
{
	//若发生错误
	throw Ab("BBB", 9, "BBBB");
}
void show()
{
	AAA();
	BBB();
}
int main()
{
	try {
		show();
	}
	catch (A& a)
	{
		cout << a.what() << endl;
	}
	return 0;
}

结果:

 2.2C++标准库的异常体系

C++ 提供了一系列标准的异常,我们可以在程序中使用这些标准的异常。它们是以父子类层次结构组织起来的。

image-20221003162517595

① 在上述继承体系中,每个类都有提供了构造函数、复制构造函数、和赋值操作符重载。

② logic_error类及其子类、runtime_error类及其子类,它们的构造函数是接受一个string类型的形式参数,用于异常信息的描述

③ 所有的异常类都有一个what()方法,返回const char* 类型(C风格字符串)的值,描述异常信息。

对异常的一写说明:

 

简单看个例子:

 

2.3异常规范

1.在函数后加上throw(类型A,类型B)可以列出这个函数能抛出的所有异常类型

void test() throw(string,vector<int>);

2,如果只跟一个类型,代表该函数只会抛出一种类型的异常

void* operator new(size_t size) throw (std::bad_alloc);

3.如果跟的是throw()代表这个函数不会抛出异常

void* test(size_t sz, void* p) throw();

4.noexcept来标识不会抛出异常

void* test(size_t sz, void* p) noexcept;

例如:

 

3.异常的优缺点

3.1优点

1.将异常对象定义好后,相比错误码的方式可以清晰准确的展示出错误的各种信息,更加直观。

2.传统返回错误码的方式去返回错误码时,需要层层返回。

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

4. 部分函数使用异常更好处理,比如构造函数没有返回值,不方便使用错误码方式处理。比如 T& operator这样的函数,如果pos越界了只能使用异常或者终止程序处理,没办法通过返回 值表示错误。

 3.2缺点

1.异常的执行流跳动比较大,有时可能很难追踪错误。

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

3.异常需要规范去使用,依赖用户的规范,习惯。

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

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

相关文章

浮点类型的比较

浮点类型的比较一.浮点数精度的损失二.浮点数的比较1.方法一2.方法二3.方法三&#xff1a;系统方案一.浮点数精度的损失 关于浮点数的比较就不得不提到浮点数在内存中的存储&#xff0c;但这里篇幅太大&#xff0c;故我将其放在另一篇博客里&#xff0c;&#xff08;如果不了解…

laravel对于百万级别数据导出的一些经验

业务上的需求&#xff0c;我们开发的供应链系统某些业务表也陆续突破了百万级别。 原先使用 \Maatwebsite\Excel 插件导出的效率越来越慢&#xff0c;5w条数据导出基本要达到20min&#xff0c;甚至于30w数据导出基本上都超时。 为了解决这个问题&#xff0c;多种尝试&#xf…

AI 让观众成为 3D 版《老友记》的导演了?

《老友记》上线 3D 版了&#xff1f; 允许用户旋转镜头&#xff0c;且从近景切换到全景观看故事&#xff1f; 今年出炉的 3D 方向 AI 项目 SitCom3D&#xff0c;能够自动补齐《老友记》原剧中的三维拍摄空间&#xff0c;用户可以选择主视图、侧视图等不同角度欣赏剧集。镜头的…

[ vulhub漏洞复现篇 ] solr 远程命令执行 (CVE-2019-17558)

&#x1f36c; 博主介绍 &#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 _PowerShell &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 &#x1f389;点赞➕评论➕收藏 养成习…

优秀的内部知识库对企业的重要性

我们都知道在客户服务方面&#xff0c;选择正确的知识库软件的重要性。但我们经常忘记的是&#xff0c;我们的员工也是我们的客户。根据盖洛普公司最近的研究&#xff0c;世界正在经历一场员工参与危机。只有大约三分之一的美国员工在工作中具有参与感&#xff0c;而在全球范围…

一文读懂Docker、K8s

目标&#xff1a; docker原理以及在运维工作的地位和作用&#xff0c;运维工作进化论&#xff0c;docker、微服务、k8s的联系、devops和docker的关系&#xff0c;docker的前世今生容器、镜像和仓库、容器和虚拟化&#xff0c;优势和劣势&#xff0c;底层的核心容器除了docker还…

什么是项目管理软件,能带来哪些作用?

在这个信息化时代&#xff0c;企业的项目管理除了需要一位出色的项目管理者外&#xff0c;还需要借助项目管理软件来对项目进行全面管理。因为如今的项目需求多样化&#xff0c;内容也愈加丰富&#xff0c;传统的项目管理方式已经难以满足&#xff0c;所以很多项目管理软件也应…

[附源码]JAVA毕业设计小型医院药品及门诊管理(系统+LW)

[附源码]JAVA毕业设计小型医院药品及门诊管理&#xff08;系统LW&#xff09; 项目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项…

CMake中add_subdirectory的使用

CMake中的add_subdirectory命令用于将子目录添加到构建&#xff0c;其格式如下&#xff1a; add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL] [SYSTEM]) source_dir指定源CMakeLists.txt和代码文件所在的目录。如果它是相对路径&#xff0c;则将相对于当前目录(…

毕业设计 - java web 酒店管理系统的设计与实现【源码+论文】

文章目录前言一、项目设计1. 模块设计总体设计具体模块数据库部分设计2. 实现效果二、部分源码项目源码前言 今天学长向大家分享一个 优秀的毕业设计项目: 酒店管理系统的设计与实现 源码获取方式: https://gitee.com/sinonfin/L-javaWebSha/tree/master 一、项目设计 1. 模…

FreeRTOS任务切换过程深层解析

FreeRTOS 系统的任务切换最终都是在 PendSV 中断服务函数中完成的&#xff0c;uCOS 也是在 PendSV 中断中完成任务切换的。 【为什么用PendSV异常来做任务切换】 PendSV 可以像普通中断一样被 Pending&#xff08;往 NVIC 的 PendSV 的 Pend 寄存器写 1&#xff09;&#xff…

Spark零基础入门实战(五)使用Eclipse创建Scala项目

本节讲解在Windows中使用Scala for Eclipse IDE编写Scala程序。 安装Scala for Eclipse IDE Scala for Eclipse IDE为纯Scala和混合Scala与Java应用程序的开发提供了高级编辑功能,并且有非常好用的Scala调试器、语义突出显示、更可靠的JUnit测试查找器等。 Scala for Eclip…

重磅首发!腾讯前晚最新爆出的“JVM学习笔记”,GitHub已评“钻级”,看完我爱了!

前言 “JVM”&#xff0c;一个虚构出来的计算机&#xff0c;是通过在实际的计算机上仿真模拟各种计算机功能来实现的。有了JVM后&#xff0c;Java语言在不同平台上运行时不需要重新编译&#xff0c;为我们提供了极大的便利性&#xff0c;现在在面试当中“JVM”相关的知识是必问…

5分钟部署云计算|云原生监控平台Prometheus-尚文网络xUP楠哥

~~全文共1277字&#xff0c;阅读需约5分钟。 进Q群11372462&#xff0c;领取专属报名福利&#xff0c;包含云计算学习路线图代表性实战训练大厂云计算面试题资料! # Prometheus介绍 Prometheus是由Go编写的时间序列监控数据库&#xff0c;在目前云计算|云原生时代非常流行&am…

分析linux内核qspi驱动层次

【推荐阅读】 需要多久才能看完linux内核源码&#xff1f; 概述Linux内核驱动之GPIO子系统API接口 https://mp.csdn.net/mp_blog/creation/editor/127819883 一篇长文叙述Linux内核虚拟地址空间的基本概括 纯干货&#xff0c;linux内存管理——内存管理架构&#xff08;建议收藏…

【LeetCode每日一题】——237.删除链表中的节点

文章目录一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【解题思路】七【题目提示】八【时间频度】九【代码实现】十【提交结果】一【题目类别】 链表 二【题目难度】 中等 三【题目编号】 237.删除链表中的节点 四【题目描述】 有一个单链…

[附源码]JAVA毕业设计小区失物招领网站(系统+LW)

[附源码]JAVA毕业设计小区失物招领网站&#xff08;系统LW&#xff09; 项目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术…

网红家电逐渐沉寂,家电企业如何利用APS排产调整生产?

随着生活水平的提高&#xff0c;近年来的消费行业逐渐呈现出消费升级、个性化、多元化趋势。在这些趋势下&#xff0c;一大批网红小家电产品迅速出现&#xff0c;以创新性的功能和设计&#xff0c;满足消费者新需求。 近年来&#xff0c;小家电领域已经成为网红爆款产品的集中地…

OpenAI ChatGPT注册步骤(超详细!!!)

最近&#xff0c;很火的OpenAI ChatGPT&#xff0c;大伙都跃跃欲试。 由于注册过程比较麻烦&#xff0c;我整理了一下注册步骤。 一、前期准备&#xff1a; 1、梯子&#xff08;需要科学上网&#xff0c;准备墙外代理&#xff09; 2、国外接码平台&#xff0c;推荐sms-activ…

java计算机毕业设计ssm学生课堂考勤小程序947n4(附源码、数据库)

java计算机毕业设计ssm学生课堂考勤小程序947n4&#xff08;附源码、数据库&#xff09; 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xf…