异常处理
参考:cnblogs
异常和错误(bug)
异常:是程序开发过程中必须考虑的一些特殊情况,是程序运行时可以预料的执行分支。异常是不可以避免的,如0除问题,数组越界问题,文件不存在问题等。但是可以处理,通过抛出,捕获异常,可以使程序继续运行。
错误:是程序的缺陷,是程序运行时无法预料的运行方式,一旦发生错误,程序将会被终止。
如:
遇到错误时:
#include<iostream>
using namespace std;
int main(){
const int a=10;
a++;
}
程序会终止运行
而遇到异常时,可以抛出,捕获,程序不会因为异常而终止运行,而是在抛出异常后继续运行后续代码
#include<iostream>
using namespace std;
void divide(int x,int y){
if(y==0){
throw -1;
}
cout<<x/y;
}
int main(){
try{
divide(20,0);
}catch(int){
cout<<"零除异常"<<endl;
}
cout<<"over"<<endl;
}
如上,在遇到异常时,throw抛出一个表达式,可以是任意类型的,但是catch时要和throw抛出的表达式类型相同,如这里抛出-1,catch就要捕获int,如果抛出了"exception"这样的字符串,catch就要捕获const char*类型。
捕获完就可以处理异常,处理异常的过程是直接跳转到catch语句后,throw后面的语句便不再执行。
如:
#include<iostream>
using namespace std;
int main(){
try{
cout<<"hello";
throw -1;
cout<<"Tom";
}catch(int a){
cout<<"异常:"<<a<<endl;
}
}
throw 出异常后,其后面的输出不再执行
且如上,catch捕获的不止throw表达式类型,同时可以赋给一个变量,然后在catch块中使用
异常的基本原则
- 通常,异常的抛出和捕获并不是在同一个函数中进行的,假设在函数B()中遇到了异常,并不会直接在B中捕获处理异常,而是抛出给它的调用者假设为A(),
B(){
...
throw -1;
}
A(){
try{
B();
}catch(int){
...
}
}
如果A中没有捕获异常,程序将会自动继续向上抛出给A的调用者,一直到main()函数,如果都没有捕获异常,程序将终止执行
-
一个try语句后可以跟多个catch语句,捕获多种类型的异常,但至少有一个catch块
-
使用catch(...)可以捕获任意类型的异常
-
异常只能被一个catch捕获,一旦被捕获,其他的catch就没有捕获机会了
try..catch嵌套(在catch中重新抛出异常)
try...catch可以嵌套使用,也就是内层的catch捕获到异常后什么都不做,直接抛出,由上一层的catch来处理异常,如:
#include<iostream>
using namespace std;
int main(){
try{
try{
cout<<"内层抛出异常"<<endl;
throw -1;
}catch(int){
throw 'a';
}
}catch(char){
cout<<"外层处理异常"<<endl;
}
}
为什么要在catch语句中重新抛出异常?
第三方库的异常解释可读性很差,甚至需要查手册才能知道什么异常,比如直接抛出一些数值,像windows系统中常见的error:-1,error:#0x0081之类的,根本不可能通过这些信息知晓异常的详情
所以在引入第三方库后,如果遇到这些异常,就捕获了重新抛出,然后加入一些自定义的解释,来增加可读性
模拟:
#include<iostream>
using namespace std;
void lib(){
throw -1;
}
void myfunc(){
try{
lib();
}catch(int a){
if(a==-1){
throw "参数错误";
}
}
}
int main(){
try{
myfunc();
}catch(const char* str){
cout<<"发生异常:"<<str<<endl;
}
}
自定义异常类
异常类是可以自定义的,用于整个大工程,将通用的异常集合起来管理。且异常类通常也会有派生类,一般也类似一个Exception父类,派生多种不同的异常类。在赋值兼容性原则中,一般将匹配子类异常的catch放在上部,匹配父类异常的catch放在下部。
例子:
#include<iostream>
using namespace std;
class Exception{
private:
int Eid;
string Edes;
public:
Exception(int id,string des){
Eid=id;
Edes=des;
};
int getEid(){return Eid;};
string getEdes(){return Edes;};
};
void lib(){
throw -1;
}
void myfunc(){
try{
lib();
}catch(int a){
if(a==-1){
throw Exception(-1,"参数错误");
}
}
}
int main(){
try{
myfunc();
}catch(Exception e){
cout<<"发生异常:"<<e.getEid()<<e.getEdes()<<endl;
}
}