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