【C++】异常处理 ⑦ ( 异常类的继承层次结构 | 抛出 / 捕获 多个类型异常对象 | 抛出子类异常对象 / 捕获并处理 父类异常对象 )

文章目录

  • 一、抛出 / 捕获 多个类型异常对象
    • 1、抛出 / 捕获 多个类型异常对象
    • 2、操作弊端
    • 3、完整代码示例
  • 二、异常类的继承层次结构
    • 1、抛出子类异常对象 / 捕获并处理 父类异常对象
    • 2、完整代码示例 - 抛出子类异常对象 / 捕获并处理 父类异常对象


自定义的 异常类 , 可能存在 继承结构 ,

也就是说 在 同一个 try-catch 代码块中 , 如果需要 拦截 和 处理多个 异常时 ,

如果 这些异常都继承相同的父类 , 只需要拦截一个 父类异常即可 ,

本篇博客中 , 讨论 抛出 / 捕获 的 异常类 存在 继承结构 的情况 ;





一、抛出 / 捕获 多个类型异常对象




1、抛出 / 捕获 多个类型异常对象


定义一个函数 , 传入一个 int 类型的参数 , void fun(int a) , 判定传入的参数值大小 ;

只有参数为 60 的时候 , 符合要求 , 其它情况下 , 一律抛出异常 ,

  • 如果参数为负数 , 抛出 eNegative 异常 ;
  • 如果参数为 0 , 抛出 eZero 异常 ;
  • 如果参数 小于 60 , 抛出 eTooSmall 异常 ;
  • 如果参数 大于 60 , 抛出 eTooBig 异常 ;

首先 , 定义上述异常类 , 定义 4 个 自定义异常类 ;

class eNegative {};
class eZero {};
class eTooBig {};
class eTooSmall {};

然后 , 在函数中 , 根据不同的判断 , 抛出不同的异常 ,

// 1. 在 函数 中 抛出异常
void fun(int a) {// 判定数字大小, 只有 60 时是合法的// 只要传入的参数不是 60 就需要抛出不同的异常if (a == 60) {// 合法}else if (a < 0) {throw eNegative();}else if (a == 0) {throw eZero();}else if (a < 60) {throw eTooSmall();}else if (a > 60) {throw eTooBig();}
}

最后 , 在 try-catch 代码块中 , 捕获异常 , 需要将 4 个异常 , 各自捕获一次 ;

	// 2. 捕获并处理异常try{// 调用可能产生异常的函数fun(0);}catch (eNegative& e) {cout << "参数是负数" << endl;}catch (eZero & e) {cout << "参数是 0" << endl;}catch (eTooSmall & e) {cout << "参数太小" << endl;}catch (eTooBig & e) {cout << "参数太大" << endl;}catch (...) {cout << "未知异常" << endl;}

2、操作弊端


上述操作 , 有一个弊端 , 那就是每次拦截处理异常时 , 都要手动编写多个 catch 分支 , 每个 catch 分支都要进行各自的操作 ;

如果要在多个位置 , 拦截处理异常 , 则需要编写的代码就太多了 ; 后期维护起来很复杂 ;


3、完整代码示例


代码示例 :

#include "iostream"
using namespace std;class eSize {};
class eNegative {};
class eZero {};
class eTooBig {};
class eTooSmall {};// 1. 在 函数 中 抛出异常
void fun(int a) {// 判定数字大小, 只有 60 时是合法的// 只要传入的参数不是 60 就需要抛出不同的异常if (a == 60) {// 合法}else if (a < 0) {throw eNegative();}else if (a == 0) {throw eZero();}else if (a < 60) {throw eTooSmall();}else if (a > 60) {throw eTooBig();}
}int main() {// 2. 捕获并处理异常try{// 调用可能产生异常的函数fun(0);}catch (eNegative& e) {cout << "参数是负数" << endl;}catch (eZero & e) {cout << "参数是 0" << endl;}catch (eTooSmall & e) {cout << "参数太小" << endl;}catch (eTooBig & e) {cout << "参数太大" << endl;}catch (...) {cout << "未知异常" << endl;}cout << "try-catch 代码块执行完毕" << endl;// 控制台暂停 , 按任意键继续向后执行system("pause");return 0;
};

执行结果 :

参数是 0
try-catch 代码块执行完毕
请按任意键继续. . .

在这里插入图片描述





二、异常类的继承层次结构




1、抛出子类异常对象 / 捕获并处理 父类异常对象


如果 抛出 / 捕获 多个类型的异常对象 , 每次拦截处理异常时 , 都要手动编写多个 catch 分支 , 不利于代码维护 ;

如果将 相似类型的异常 都继承自 一个父类 , 那么每次拦截时 , 只需要拦截一个父类异常即可 ;


定义父类异常 , 其中定义一个纯虚函数 , 该纯虚函数是异常打印 , 或者异常处理的通用操作 ;

class eSize {
public:virtual void printError() = 0;
};

剩余的 4 个异常类 , 都继承 异常类父类 , 并实现纯虚函数 ;

class eNegative : public eSize {
public:virtual void printError() {cout << "参数是负数" << endl;}
};
class eZero : public eSize {
public:virtual void printError() {cout << "参数是 0" << endl;}
};
class eTooBig : public eSize {
public:virtual void printError() {cout << "参数太大" << endl;}
};
class eTooSmall : public eSize {
public:virtual void printError() {cout << "参数太小" << endl;}
};

上述定义的纯虚函数 , 会发生多态 ;

在拦截父类对象时 , 调用不同的 异常对象 , 会分别调用不同子类的 虚函数方法 ;


抛出异常的函数如下 , 抛出异常时 , 需要抛出子类异常对象 ;

// 1. 在 函数 中 抛出异常
void fun(int a) {// 判定数字大小, 只有 60 时是合法的// 只要传入的参数不是 60 就需要抛出不同的异常if (a == 60) {// 合法}else if (a < 0) {throw eNegative();}else if (a == 0) {throw eZero();}else if (a < 60) {throw eTooSmall();}else if (a > 60) {throw eTooBig();}
}

捕获并处理异常时 , 只需要拦截 父类异常对象即可 ;

	// 2. 捕获并处理异常try{// 调用可能产生异常的函数fun(0);}catch (eSize& e) {e.printError();}catch (...) {cout << "未知异常" << endl;}

2、完整代码示例 - 抛出子类异常对象 / 捕获并处理 父类异常对象


代码示例 :

#include "iostream"
using namespace std;class eSize {
public:virtual void printError() = 0;
};
class eNegative : public eSize {
public:virtual void printError() {cout << "参数是负数" << endl;}
};
class eZero : public eSize {
public:virtual void printError() {cout << "参数是 0" << endl;}
};
class eTooBig : public eSize {
public:virtual void printError() {cout << "参数太大" << endl;}
};
class eTooSmall : public eSize {
public:virtual void printError() {cout << "参数太小" << endl;}
};// 1. 在 函数 中 抛出异常
void fun(int a) {// 判定数字大小, 只有 60 时是合法的// 只要传入的参数不是 60 就需要抛出不同的异常if (a == 60) {// 合法}else if (a < 0) {throw eNegative();}else if (a == 0) {throw eZero();}else if (a < 60) {throw eTooSmall();}else if (a > 60) {throw eTooBig();}
}int main() {// 2. 捕获并处理异常try{// 调用可能产生异常的函数fun(0);}catch (eSize& e) {e.printError();}catch (...) {cout << "未知异常" << endl;}cout << "try-catch 代码块执行完毕" << endl;// 控制台暂停 , 按任意键继续向后执行system("pause");return 0;
};

执行结果 :

参数是 0
try-catch 代码块执行完毕
请按任意键继续. . .

在这里插入图片描述

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

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

相关文章

23.12.3日总结

饿了么项目进度 新建菜品的添加属性&#xff1a; 适应不同尺寸的媒体查询&#xff1a; 菜品详细页面&#xff1a; 项目上遇到的问题 媒体查询遇到的问题&#xff1a; 关于媒体查询不能生效的原因-CSDN博客 答辩总结 js中声明变量的关键字&#xff08;const&#xff0c;let…

初始化 Clouder Manager 数据库报错Unable to find JDBC driver for database type: MySQL

CDH部署初始化 Clouder Manager 数据库报错。 解决方法&#xff1a; 把mysql驱动放到 /usr/share/java/目录下面(没有的新建&#xff09;&#xff0c;驱动名称也要修改为mysql-connector-java.jar 再次执行后成功&#xff1a; sudo /opt/cloudera/cm/schema/scm_prepare_data…

SpringBoot之自定义Starter

目录 一、自己的理解 1. 理解一 2. 理解二 二、自定义starter&#xff08;重点&#xff09; 三、以mybatis-spring-boot-starter为例进行分析 1. 写好自己的自动配置类逻辑 2. 创建自己的starter项目并引入自动配置类项目的依赖 3. 在其它项目中使用自定义的starter 一…

[ 云计算 | AWS 实践 ] 使用 Java 检查指定的密钥是否存在于给定的 Amazon S3 存储桶中

本文收录于【#云计算入门与实践 - AWS】专栏中&#xff0c;收录 AWS 入门与实践相关博文。 本文同步于个人公众号&#xff1a;【云计算洞察】 更多关于云计算技术内容敬请关注&#xff1a;CSDN【#云计算入门与实践 - AWS】专栏。 本系列已更新博文&#xff1a; [ 云计算 | …

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…

虚拟化逻辑架构: VM VirtualBox 指定6.0.24版本开启硬件辅助虚拟化功能

目录 一、实验 1.安装VM VirtualBox-6.0.24 2.安装VM VirtualBox-6.1.26 3.再次重新安装VM VirtualBox-6.0.24 二、问题 1.系统开机报错 2.Ubuntu系统无法自适应VM VirtualBox系统边框 3.VirtualBox如何开启无缝模式 3.Ubuntu如何查询软件是否已经安装 一、实验 1.安…

react二次封装Modal和Drawer组件

目录 react二次封装Modal和Drawer组件01&#xff1a;Modal组件01-1 BaseModal.jsx01-2 使用BaseModal组件01-3 效果 02&#xff1a;Drawer组件02-1 BaseDrawer.jsx组件02-2 使用BaseDrawer组件02-3效果 react二次封装Modal和Drawer组件 npm i styled-components 01&#xff1…

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

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

[RoFormer]论文实现:ROFORMER: ENHANCED TRANSFORMER WITH ROTARY POSITION EMBEDDING

文章目录 一、完整代码二、论文解读2.1 注意力机制2.2 绝对位置编码2.3 相对位置编码2.4 旋转位置编码Long-term decayAdaption for linear attention 2.5 模型效果 三、过程实现四、整体总结 论文&#xff1a;ROFORMER: ENHANCED TRANSFORMER WITH ROTARY POSITION EMBEDDING …

Java 使用itextpdf创建Pdf文件

DOM文件添加Maven依赖 <dependency><groupId>com.itextpdf</groupId><artifactId>itext7-core</artifactId><version>7.2.0</version><type>pom</type></dependency> 主要代码&#xff1a; PdfFont font PdfFo…

yo!这里是智能指针相关介绍

目录 前言 内存泄漏 RAII 智能指针原理 智能指针分类 auto_ptr unique_ptr shared_ptr 两个问题 线程安全 循环引用 后记 前言 对于智能指针&#xff0c;听起来很高大上&#xff0c;其实本质上就是一个类。为什么叫指针呢&#xff1f;因为可以像指针一样管理一块资…

linux 应用开发笔记---【I/O文件/基础篇 】

文章笔记来自于【速学Linux】手把手教你学嵌入式Linux C应用编程_哔哩哔哩_bilibili 一&#xff0c;什么是linux应用程序 1.运行在linux操作系统用户空间的程序 2.内核程序运行在内核空间&#xff0c;应用程序运行在用户空间 在终端执行的命令ls,ps。。。。。。都是运行在用…

【MySQL的DQL查询语句】

MySQL的DQL查询语句-----在Navicat下 将学生表导入Navicat中查询语句查询一整张表查询年龄大于22年龄大于22的女生查找文科的学生查找六班的学生计算学生的总分 &#xff08;group by&#xff09;合并两表 &#xff08;join on xxxx&#xff09;合并两张表 并求总分先合并在聚合…

Java+springboot+avue医院绩效考核系统源码支持二次开发

公立医院改革要求建立公立医疗卫生机构绩效考核体系&#xff0c;借助绩效考核来引导各级公立医院把社会效益摆在首位&#xff0c;提高医疗服务质量&#xff0c;规范医疗服务行为&#xff0c;加强医院内部管理&#xff0c;促进医院高质量发展 医院绩效考核系统&#xff0c;建立以…

python 运用pandas 库处理excel 表格数据

文章目录 读取文件查看数据数据选择数据筛选创建新列计算并总结数据分组统计 读取文件 Pandas 是一个强大的数据分析库&#xff0c;它提供了丰富的数据结构和数据分析工具&#xff0c;其中之一是用于读取不同格式文件的 read_* 函数系列。以下是一个简单介绍如何使用 Pandas 读…

Siemens-NXUG二次开发-C/C++/Python环境配置[20231204]

Siemens-NXUG二次开发-C/C/Python运行方式[20231204] 1.NX/UG C/C/Python API官方开发文档2.运行方式2.1内部模式2.2 外部模式2.3 许可证书服务器启动 3.C/C环境配置4.Python环境配置5.第三方环境配置 1.NX/UG C/C/Python API官方开发文档 西门子NX/UG Python api开发文档&…

Spring学习笔记:Day2

昨天定的学习计划发现通过文心4.0来实现不靠谱&#xff0c;坑太多&#xff0c;今天开始跟随B站进行学习&#xff0c;争取10-15天学习一遍&#xff0c;冲啊&#xff01; 地址&#xff1a;001-课程介绍_哔哩哔哩_bilibili 今日规划&#xff1a; pt 001 - pt 018&#xff0c;提到…

小心处理 C++ 静态变量中的陷阱

小心处理 C 静态变量中的陷阱 函数中的 static 变量 static 变量的作用 C 中 static 关键字的最后一个用途是在函数内创建局部变量&#xff0c;这些变量在其作用域内退出和进入时保持其值。函数内的 static 变量类似于只能从该函数访问的全局变量。static 变量的一个常见用途…

【UGUI】实现背包的常用操作

1. 添加物品 首先&#xff0c;你需要一个包含物品信息的类&#xff0c;比如 InventoryItem&#xff1a; using UnityEngine;[CreateAssetMenu(fileName "NewInventoryItem", menuName "Inventory/Item")] public class InventoryItem : ScriptableObje…

网工学习7-配置 GVRP 协议

7.1GARP概述 GARP(Generic Attribute Registration Protocol)是通用属性注册协议的应用&#xff0c;提供 802.1Q 兼容的 VLAN 裁剪 VLAN pruning 功能和在 802.1Q 干线端口 trunk port 上建立动态 VLAN 的功能。 GARP 作为一个属性注册协议的载体&#xff0c;可以用来传播属性…