目录
处理异常的方式
c
c++
异常的使用
异常的抛出和捕获
异常的重新抛出
异常安全
异常规范
自定义异常体系
c++标准库中的异常体系
异常的优缺点
处理异常的方式
c:
1、终止程序,使用assert
2、返回错误码,c中一般用errno接收
c++
抛异常,面向对象的语言都是用抛异常来解决错误信息
当一个函数发现自己无法处理错误信息时候,就会使用抛异常来直接或间接处理这个错误信息
try:try中为保护的代码,假如有错误,将会抛出异常,后接多个catch
catch:接收异常,可以有多个catch来捕获异常
throw:假如为错误,则抛出异常,throw可以抛出任意类型的信息,具体看自己如何处理信息
异常的使用
异常的抛出和捕获
#include
using namespace std;
int mul(int x, int y)
{
if (y == 0)
throw "除0错误"; //抛出异常的指令,假如出现异常则抛出
return x / y;
}
int main()
{
int x, y;
cin >> x >> y;
try //被保护的代码
{
cout << mul(x, y) << endl;
}
catch (const char* c) //接收异常的地方
{
cout << c << endl;
}
return 0;
}
#includeusing namespace std; int mul(int x, int y) { if (y == 0) throw "除0错误"; //抛出异常的指令,假如出现异常则抛出 return x / y; } int main() { int x, y; cin >> x >> y; try //被保护的代码 { cout << mul(x, y) << endl; } catch (const char* c) //接收异常的地方 { cout << c << endl; } return 0; }
注意事项:
1、异常必须被捕获,不然程序直接终止,当异常被捕获的时候,只会跳转到catch处,后面程序会继续执行
2、异常捕获类型必须和抛出类型相匹配(特例:派生类抛出的异常,可以由基类进行捕获)
异常匹配原则:
1,先从本函数进行查找
2、假如没有找到返回上一层函数
3、当返回到main函数还是没有找到catch的时候,程序就会终止报错(catch可以捕获任意类型的异常)
异常的重新抛出
在有些场景下,为了防止执行语句跳转产生一些问题,比如没有delete之类的,我们可以先提前将异常捕获,进行特殊处理后,在将异常抛出
#includeusing namespace std; int mul(int x, int y) { if (y == 0) throw "除0错误"; //抛出异常的指令,假如出现异常则抛出 return x/y; } void f() { int* z = new int; int x, y; cin >> x >> y; try //被保护的代码 { cout << mul(x, y) << endl; } catch (const char* c) //提前catch异常 { delete z; throw; //将异常重新抛出 } delete z; } int main() { try //被保护的代码 { f(); } catch (const char* c) //重新接收异常的地方 { cout << c << endl; } return 0; }
异常安全
1、构造函数最好别抛异常,否则可能导致对象不完整,或者没完全初始化
2、析构函数最好不要抛异常,否则可能导致内存泄露
异常规范
1、在函数后面throw(类型),说明这个函数可能抛出哪种类型的异常
int add(int x, int y)throw(char, int) //函数后面添加throw(typename...)
{}
2、throw(),表示这个函数不会抛异常
int add(int x, int y)throw() //函数后面添加throw()
{}
3、假如没有声明,则函数可能抛任意类型的异常
自定义异常体系
为了方便我们管理异常,所以我们可以创建一个专门的类,来编写拥有哪些异常
一般包含错误码和错误信息
为了更加简便的抛出异常,我们可以抛出定义一个基类,抛出派生类的异常,然后由基类接收,这样就可以更加便捷的使用异常了
c++标准库中的异常体系
基类:
其他类直接或间接的继承基类,进行异常处理
异常的优缺点
优点:
1、更加清晰的展示出错误的各种信息
2、比获取错误码更加的方便,错误码每个调用的地方都要检查一遍返回值,而抛异常可以直接在出错地方抛出,外面进行捕获
3、可以接受很多库中的异常
4、构造析构函数没有返回值来进行错误信息的处理,这个时候就需要使用异常(虽然构造析构函数最好不要使用异常)
缺点:
1、执行程序混乱
2、性能开销(很低)
3、异常安全
4、标准异常库不好用,公司一般自己创建自己的异常库
5、函数抛异常不规范



