【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,一经查实,立即删除!

相关文章

浅析SD-WAN技术如何加强企业网络安全

在这个数字化时代&#xff0c;企业组网的安全性已经成为许多企业所面临的一个重要挑战。特别是随着云计算、移动办公等新型信息技术的普及&#xff0c;企业网络的规模和复杂度不断增加&#xff0c;网络攻击和数据泄露的威胁也日益增加。因此&#xff0c;企业需要采取更加有效的…

西南科技大学C++程序设计实验三(类与对象二)

一、实验目的 1.理解类的复制构造函数的定义、说明与使用 2.扩充类的数据成员,为其增加静态数据成员、常(const)成员、其他类定义的成员等 3.理解组合类的相关知识点 二、实验任务 阅读分析、完善程序。下面是一个学生类student的定义,数据成员包括一个代表姓名字符个数的…

23.12.3日总结

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

c语言编程题经典100例——(61~65例)

1&#xff0c;写一个函数&#xff0c;判断一个数是否为正数。 #include <stdio.h> #include <stdbool.h> bool isPositive(int num) { if (num > 0) { return true; } else { return false; } }int main() { int num, cube; printf("请输入一个…

初始化 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 一…

c++遍历算法的transform算法

transform 算法函数用于对指定范围内的元素进行一个操作&#xff0c;并将结果存储到另一个范围中。 template<class InputIterator, class OutputIterator, class UnaryOperation> OutputIterator transform(InputIterator first, InputIterator last, OutputIterator r…

共享智能指针shared_ptr

共享智能指针 在C中没有垃圾回收机制&#xff0c;必须自己释放分配的内存&#xff0c;否则就会造成内存泄露。解决这个问题最有效的方法是使用智能指针&#xff08;smart pointer&#xff09;。智能指针是存储指向动态分配&#xff08;堆&#xff09;对象指针的类&#xff0c;…

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

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

C++ 智能指针和内存管理:使用指南和技巧

C是一门强大的编程语言&#xff0c;但是在内存管理方面却存在着一些问题。手动管理内存不仅费时费力&#xff0c;而且容易出错。因此&#xff0c;C中引入了智能指针这一概念&#xff0c;以更好地管理内存。 什么是智能指针&#xff1f; 在C中&#xff0c;内存的分配和释放都是…

AttributeError: ‘FieldInfo‘ object has no attribute ‘required‘.

诸神缄默不语-个人CSDN博文目录 这个bug是在安装doccano包之后&#xff0c;在运行transformers代码时出现的。 核心报错信息&#xff1a; RuntimeError: Failed to import transformers.models.bert.modeling_bert because of the following error (look up to see its trac…

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…

服务器入侵如何防护,业务被攻击如何处理,服务器安全防护方案

服务器是算是家用电脑的一种使用方法,主机不在用户家中,需要远程使用,在目前互联网时代占用很重要的位置&#xff0c;当然生活中也是应用广泛。服务器比普通计算机运行更快、负载更高、价格更贵。很多娱乐,工作都需要依靠服务器来运行整个体系&#xff0c;因此服务器的安全防护…

虚拟化逻辑架构: 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.安…

SCAU:主对角线上的元素之和

主对角线上的元素之和 Time Limit:1000MS Memory Limit:65535K 题型: 编程题 语言: G;GCC 描述 输入一个3行4列的整数矩阵&#xff0c;计算并输出主对角线上的元素之和输入格式 3行4列整数矩阵输出格式 主对角线上的元素之和输入样例 1 2 3 4 5 6 7 8 9 10 11 12输出…

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…

详细学习PyQt5中的多线程

Pyqt5相关文章: 快速掌握Pyqt5的三种主窗口 快速掌握Pyqt5的2种弹簧 快速掌握Pyqt5的5种布局 快速弄懂Pyqt5的5种项目视图&#xff08;Item View&#xff09; 快速弄懂Pyqt5的4种项目部件&#xff08;Item Widget&#xff09; 快速掌握Pyqt5的6种按钮 快速掌握Pyqt5的10种容器&…

【Shell3】日常巡检1

#!/usr/bin/env bash# --------------------------------------------------------------------------------- # 控制台颜色 BLACK"\033[1;30m" RED"\033[1;31m" GREEN"\033[1;32m" YELLOW"\033[1;33m" BLUE"\033[1;34m" PU…

go语言学习-包管理

1、概念 1.1 什么是包 ***Go语言的包(package) ***是一种源码封装的方式,可以被看做是组相关的,并且通用的代码集合。这些包都有自己的独立的功能,然后在编写代码时,如果需要用到这些功能,可以导入包直接使用。 打印一些内容:fmt处理一些时间相关的: time处理一些数学相关…

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

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