【C++】异常处理 ⑦ ( 异常类的继承层次结构 | 抛出 / 捕获 多个类型异常对象 | 抛出子类异常对象 / 捕获并处理 父类异常对象 )
  K1I6GvxBEuyy 2023年12月10日 36 0



文章目录

  • 一、抛出 / 捕获 多个类型异常对象
  • 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 代码块执行完毕
请按任意键继续. . .

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






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




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 代码块执行完毕
请按任意键继续. . .

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


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年12月10日 0

暂无评论

推荐阅读
K1I6GvxBEuyy
作者其他文章 更多
最新推荐 更多

2024-05-17