C++-第十九章:异常

目录

第一节:异常有哪些

第二节:异常相关关键字

        2-1.抛出异常

        2-2.捕获异常

        2-3.异常的捕获规则 

                2-3-1.异常被最近的catch捕获

                2-3-2.catch捕获的是异常的拷贝

                2-3-3.异常为子类时,可以用父类引用接收

         2-4.捕获任意异常

第三节:异常使用规范

下期预告:


第一节:异常有哪些

        异常的本质是一个数据,它可以是内置类型、也可以是自定义类型,但是它的数据发生了出乎意料的错误,例如一个购票系统中的剩余票数肯定不是负数,如果发现是负数,说明程序出现了BUG,此时将剩余票数抛出。外部就会接收到这个数据,然后执行处理程序处理这个异常,或者由程序员来修复BUG。

        总之,异常是一种错误的处理方式,让函数直接或者间接的调用者进行处理。

第二节:异常相关关键字

        2-1.抛出异常

        使用 throw 关键字来向外抛出异常:

void func1()
{int a = 0;if (a == 0) // a为0就将其视作异常进行抛出throw a; // 异常抛出后不会再执行后面的函数,而是直接跳出异常std::cout << "我不会被执行了" << std::endl;
}

        当 func 被调用时,它就会抛出异常,异常的类型是a,值为0。

        而且异常抛出后,该函数后面的代码也不会再执行了。

        2-2.捕获异常

        使用 try{}catch{} 的组合来捕获并处理异常, try{} 中存放可能抛出异常的代码,catch{} 中存放获取异常后的处理函数:

void func1()
{int a = 0;if (a == 0) // a为0就将其视作异常进行抛出throw a; // 异常抛出后不会再执行后面的函数,而是直接跳出异常std::cout << "我不会被执行了" << std::endl;
}
int main()
{try{func1();}catch (int a) // 捕获的异常类型{std::cout << "捕获了异常:" << a << std::endl;}return 0;
}

  

        而且异常抛出后,对应 try{} 内的代码也不会继续向下执行了:

int main()
{try{func1();std::cout << "抛出异常后,我不会再被执行了" << std::endl;}catch (int a) // 捕获的异常类型{std::cout << "捕获了异常:" << a << std::endl;}return 0;
}

  

        一个 catch{} 必须配对一个 try{},而一个 try{} 可以配对多个 catch{},这样才能捕获多种类型的异常进行处理:

void func1()
{int a = 1;  // a为1if (a == 0) // a为0就将其视作异常进行抛出throw a; 
}
void func2()
{std::string str = "123";if (str == "123")throw str;
}
int main()
{try{func1();func2();}catch (int a) // 捕获的异常类型{std::cout << "捕获了异常:" << a << std::endl;}catch (std::string str){std::cout << "捕获了异常:" << str << std::endl;}return 0;
}

        为了能执行func2,将func1中的a设置为1,这样func1就不会抛出异常了。

  

        2-3.异常的捕获规则 

                2-3-1.异常被最近的catch捕获

void func1()
{int a = 0; if (a == 0)throw a;
}
void func2()
{std::string str = "123";if (str == "123")throw str;
}
void func3()
{try{func1();}catch (int a){std::cout << "我是func3的catch" << std::endl;}
}
int main()
{try{func3();func2();}catch (int a) // 捕获的异常类型{std::cout << "捕获了异常:" << a << std::endl;}catch (std::string str){std::cout << "捕获了异常:" << str << std::endl;}return 0;
}

        func1嵌套了fun3,且func3也有对应的处理异常的catch,此时func1的异常就会被func3中的catch捕获并处理。而且异常被捕获后就不会继续向外抛出了,意味着main函数是没有异常的,它的try{}就会继续向后执行:

  

                2-3-2.catch捕获的是异常的拷贝

        catch捕获的是异常的一份拷贝,真正的异常在被捕获时就销毁了:

int main()
{try{int a = 0;std::cout << &a << std::endl;throw a;}catch (int a) // 捕获的异常类型{std::cout << &a << std::endl;}return 0;
}

   

                2-3-3.异常为子类时,可以用父类引用接收

        利用多态可以使用各种派生类定制的处理函数:

class Person
{
public:Person(const std::string& name = "") :_name(name){}virtual void PrintInfo(){std::cout << _name << std::endl;}
private:std::string _name;
};class Student:public Person
{
public:Student(const std::string& name) :_name(name){}virtual void PrintInfo() override{std::cout << _name << std::endl;}
private:std::string _name;
};
int main()
{try{Student s("LiHua");throw s;}catch (Person& obj){obj.PrintInfo();}return 0;
}

   

        要保持多态性必须使用父类引用,接收子类,父类指针、单纯父类无引用都不行。

         2-4.捕获任意异常

        使用 catch(...){} 表示捕获任意异常,一般放在main函数最后,防止程序因为main函数抛出异常却没有相应的catch导致函数退出,进而导致程序崩溃。

        还可以放在其他位置,使用:

void func()
{try{//...}catch (...){throw;}
}

        表示捕获到什么异常,就抛出什么异常,catch(...){}作为保底来使用。

第三节:异常使用规范

        将 noexcept 放在函数后面表示这个函数不会抛出异常,函数也就不能放进 try{} 里了,但是它内部还是可以处理异常的:

void func() noexcept
{try{//...}catch (...){throw;}
}

         其次,在构造函数和析构函数中不要抛出异常,否则极易导致已分配的内存无法正确释放和资源不一致的问题。

        最后,抛出异常时如果没有释放锁,很可能导致死锁问题,可以用智能锁解决

下期预告:

        第二十章将详细了解智能指针。 

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

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

相关文章

Redis详解(实战 + 面试)

目录 Redis 是单线程的&#xff01;为什么 Redis-Key(操作redis的key命令) String 扩展字符串操作命令 数字增长命令 字符串范围range命令 设置过期时间命令 批量设置值 string设置对象,但最好使用hash来存储对象 组合命令getset,先get然后在set Hash hash命令: h…

‘ts-node‘ 不是内部或外部命令,也不是可运行的程序

新建一个test.ts文件 let message: string = Hello World; console.log(message);如果没有任何配置的前提下,会报错’ts-node’ 不是内部或外部命令,也不是可运行的程序。 此时需要安装一下ts-node。 npm install

(十 五)趣学设计模式 之 命令模式!

目录 一、 啥是命令模式&#xff1f;二、 为什么要用命令模式&#xff1f;三、 策略模式的实现方式四、 命令模式的优缺点五、 命令模式的应用场景六、 总结 &#x1f31f;我的其他文章也讲解的比较有趣&#x1f601;&#xff0c;如果喜欢博主的讲解方式&#xff0c;可以多多支…

基于单片机的智能扫地机器人

1 电路设计 1.1 电源电路 本电源采用两块LM7805作为稳压电源&#xff0c;一块为控制电路和传感器电路供电&#xff0c;另一块单独为电机供电。分开供电这样做的好处&#xff0c;有利于减小干扰&#xff0c;提高系统稳定性。 LM7805是常用的三端稳压器件&#xff0c;顾名思义0…

【Redis学习】Redis Docker安装,自定义config文件(包括RDB\AOF setup)以及与Spring Boot项目集成

【本文内容】 第1章&#xff1a;通过Docker安装Redis&#xff0c;并自定义config文件以及mount data目录。第2章&#xff1a;介绍Redis持久化到磁盘&#xff0c;有4种方式&#xff1a;RDB / AOF / NONE / RDB AOF。第3章&#xff1a;使用Server自带的redis-cli工具连接。第4章…

【3天快速入门WPF】13-MVVM进阶

目录 1. 窗体设置2. 字体图标3. 控件模板4. 页面逻辑4.1. 不使用MVVM4.2. MVVM模式实现本篇我们开发一个基于MVVM的登录页面,用来回顾下之前学习的内容 登录页面如下: 窗体取消了默认的标题栏,调整为带阴影的圆角窗体,左侧放一张登录背景图,右边自绘了一个关闭按钮,文本框…

PHP实现登录和注册(附源码)

前言 本博客主要讲述利用php环境实现一个简单的前后端结合的用户登录和注册功能。phpstudy是PHP调试环境的集成包&#xff0c;该程序包集成了 ApachePHPMySQLphpMyAdmin 等多个工具&#xff0c;是很好用的调试环境的程序集成包。 目录 前言 1. 准备工作 1.1 工具 1.2 php…

Redis数据结构-List列表

1.List列表 列表类型适用于存储多个有序的字符串&#xff08;这里的有序指的是强调数据排列顺序的重要&#xff0c;不是升序降序的意思&#xff09;&#xff0c;列表中的每个字符串称为元素&#xff08;element&#xff09;&#xff0c;一个列表最多可以存储2^32-1个元素。在R…

Redis 实战篇 ——《黑马点评》(下)

《引言》 &#xff08;下&#xff09;篇将记录 Redis 实战篇 最后的一些学习内容&#xff0c;希望大家能够点赞、收藏支持一下 Thanks♪ (&#xff65;ω&#xff65;)&#xff89;&#xff0c;谢谢大家。 传送门&#xff08;上&#xff09;&#xff1a;Redis 实战篇 ——《黑马…

WordPress二次开发实现用户注册审核功能

WordPress默认直接注册登录了&#xff0c;不需要任何验证&#xff0c;如果被批量注册就麻烦了&#xff0c;所以添加一个审核功能比较好。 注册用户默认需要手动审核&#xff0c;审核以后才能登陆&#xff0c;开启审核&#xff0c;可以有效防止用户批量注册。 这儿讲解一下如何…

基于SpringBoot的“青少年心理健康教育网站”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“青少年心理健康教育网站”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 系统总体结构图 实体属性图 系统首页界…

湖仓一体概述

湖仓一体之前&#xff0c;数据分析经历了数据库、数据仓库和数据湖分析三个时代。 首先是数据库&#xff0c;它是一个最基础的概念&#xff0c;主要负责联机事务处理&#xff0c;也提供基本的数据分析能力。 随着数据量的增长&#xff0c;出现了数据仓库&#xff0c;它存储的是…

React:B站评论demo,实现列表渲染、删除按钮显示和功能实现、导航栏渲染切换及高亮显示、评论区的排序

功能要求&#xff1a; 1、渲染评论列表 2、删除评论功能&#xff1a;只显示自己评论的删除按钮&#xff1b;点击删除按钮&#xff0c;删除当前评论&#xff0c;列表中不再显示。 3、渲染导航Tab&#xff08;最新 | 最热&#xff09;和其 高亮实现 4、评论排序功能实现&…

springboot系列教程(三十一):springboot整合Nacos组件,环境搭建和入门案例详解

一、Nacos基础简介 1、概念简介 Nacos 是构建以“服务”为中心的现代应用架构&#xff0c;如微服务范式、云原生范式等服务基础设施。聚焦于发现、配置和管理微服务。Nacos提供一组简单易用的特性集&#xff0c;帮助开发者快速实现动态服务发现、服务配置、服务元数据及流量管…

python爬虫报错信息解决方法

今天遇到了这样一条报错&#xff1a; opt/conda/envs/python35-paddle120-env/bin/python /home/aistudio/work/main.py aistudiojupyter-10415006-8838159:~$ /opt/conda/envs/python35-paddle120-env/bin/python /home/aistudio/work/main.py Traceback (most recent call la…

如何快速的解除oracle dataguard

有些时候&#xff0c;我们为了使oracle dg的standby库另做他用&#xff0c;需要解除oracle dataguard数据同步。我本地因为standby库存储出现故障&#xff0c;导致dg存在问题&#xff0c;故需要解除。今天&#xff0c;我们通过使用部分命令&#xff0c;实现dg的快速解除。 1&a…

【告别双日期面板!一招实现el-date-picker智能联动日期选择】

告别双日期面板&#xff01;一招实现el-date-picker智能联动日期选择 1.需求背景2.DateTimePicker 现状图3.日期选择器实现代码4.日期选择器实现效果图5.日期时间选择器实现代码6.日期时间选择器实现效果图 1.需求背景 在用户使用时间查询时&#xff0c;我们经常需要按月份筛选…

Git GitHub基础

git是什么&#xff1f; Git是一个分布式版本控制系统&#xff0c;用于管理源代码的变更。它允许多个开发者在同一个项目上协作&#xff0c;同时跟踪每个修改的历史记录。 关键词&#xff1a; 分布式版本控制软件 软件 安装到我们电脑上的一个工具 版本控制 例如论文&…

汽车无人驾驶系统中的防撞设计

一、系统方案介绍 无人驾驶汽车的防撞系统是保障行车安全的核心模块&#xff0c;本文设计的系统以STM32F103C8T6单片机为主控制器&#xff0c;结合超声波测距、WiFi通信、人机交互等模块&#xff0c;实现障碍物实时检测、动态阈值设置、多级报警和数据可视化功能。系统通过软…

深度学习笔记——线性回归的从0开始实现

记录学习到的知识&#xff1a; 语义分割是将标签或类别与图片的每个像素关联的一种深度学习算法。 它用来识别构成可区分类别的像素集合。 图像分割是一个端到端图像分析过程&#xff0c;它将数字图像分成多个片段&#xff0c;并对每个区域中包含的信息进行分类。三种图像分割…