自定义的 异常类 , 可能存在 继承结构 ,
也就是说 在 同一个 try-catch 代码块中 , 如果需要 拦截 和 处理多个 异常时 ,
如果 这些异常都继承相同的父类 , 只需要拦截一个 父类异常即可 ,
本篇博客中 , 讨论 抛出 / 捕获 的 异常类 存在 继承结构 的情况 ;
一、抛出 / 捕获 多个类型异常对象
1、抛出 / 捕获 多个类型异常对象
定义一个函数 , 传入一个 int 类型的参数 , void fun(int a) , 判定传入的参数值大小 ;
只有参数为 60 的时候 , 符合要求 , 其它情况下 , 一律抛出异常 ,
- 如果参数为负数 , 抛出 eNegative 异常 ;
- 如果参数为 0 , 抛出 eZero 异常 ;
- 如果参数 小于 60 , 抛出 eTooSmall 异常 ;
- 如果参数 大于 60 , 抛出 eTooBig 异常 ;
首先 , 定义上述异常类 , 定义 4 个 自定义异常类 ;
代码语言:javascript复制class eNegative {};
class eZero {};
class eTooBig {};
class eTooSmall {};
然后 , 在函数中 , 根据不同的判断 , 抛出不同的异常 ,
代码语言:javascript复制// 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 个异常 , 各自捕获一次 ;
代码语言:javascript复制 // 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、完整代码示例
代码示例 :
代码语言:javascript复制#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 分支 , 不利于代码维护 ;
如果将 相似类型的异常 都继承自 一个父类 , 那么每次拦截时 , 只需要拦截一个父类异常即可 ;
定义父类异常 , 其中定义一个纯虚函数 , 该纯虚函数是异常打印 , 或者异常处理的通用操作 ;
代码语言:javascript复制class eSize {
public:
virtual void printError() = 0;
};
剩余的 4 个异常类 , 都继承 异常类父类 , 并实现纯虚函数 ;
代码语言:javascript复制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;
}
};
上述定义的纯虚函数 , 会发生多态 ;
在拦截父类对象时 , 调用不同的 异常对象 , 会分别调用不同子类的 虚函数方法 ;
抛出异常的函数如下 , 抛出异常时 , 需要抛出子类异常对象 ;
代码语言:javascript复制// 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();
}
}
捕获并处理异常时 , 只需要拦截 父类异常对象即可 ;
代码语言:javascript复制 // 2. 捕获并处理异常
try
{
// 调用可能产生异常的函数
fun(0);
}
catch (eSize& e) {
e.printError();
}
catch (...) {
cout << "未知异常" << endl;
}
2、完整代码示例 - 抛出子类异常对象 / 捕获并处理 父类异常对象
代码示例 :
代码语言:javascript复制#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 代码块执行完毕 请按任意键继续. . .