【C++】C++中的异常处理try-catch
C++中的异常处理
- 1.C语言异常
- 示例代码:理解C++中的throw
- 语法格式:
- 示例代码:throw抛出的异常必须用try-catch语句来处理
- 示例代码:一个try可以对应多个catch
- 2.C++新增的异常处理方式
- 2.1 两大类型的异常:
- 示例代码:throw可抛出的几种异常
- 示例代码:利用多态的知识简写
- 3.异常声明(也叫做异常规范,C++11已经不建议使用了)
- 示例代码:(...)中省略号的作用
1.C语言异常
if(函数的返回值出错)
{C语言或者linux中的异常处理return -1; return NULL return
}if(open("文件名")==-1)
{处理错误if(errno==宏定义)}
示例代码:理解C++中的throw
#include <iostream>
#include <algorithm> //算法有关的头文件
#include <vector> using namespace std;/*如果实参>=0 成功实参<0 失败失败的时候,提示如下错误:terminate called after throwing an instance of 'int'Aborted (core dumped)中文:终止调用,函数抛出了整型异常实例原因:C++规定,如果一个函数使用throw抛出了某种异常,程序员必须使用try catch语句去捕获异常并处理,否则代码直接崩溃C++的throw,可以"逼着你处理异常"
*/
int fun(int n)
{if(n>=0)return 0; //成功elsethrow -1; //抛出整型异常,跟return -1有啥区别呢?//return -1;
}
int main()
{int ret;//函数调用成功//ret=fun(12);//函数调用失败ret=fun(-12);if(ret==0)cout<<"函数调用成功了"<<endl;else //错误的写法:throw抛出某种异常,不是用if else判断来处理,必须使用try catch语句来处理cout<<"函数调用失败了"<<endl;cout<<"主函数继续往下执行"<<endl;
}/*
上述代码编译时会报错:Aborted (core dumped)
*/
解决上述使用throw抛出异常后错误的方法:
- try-catch处理错误,如果一个函数的源码中使用了throw去抛出异常,那么程序员在调用该函数的时候就
必须
使用try-catch语句去捕捉处理异常 - throw 抛出异常/引发异常
- 异常处理程序也被称为catch块
语法格式:
try //测试函数调用是否会抛出异常 try块
{调用某个函数
}catch(异常类型) //捕捉try语句中函数调用可能抛出的错误类型,字符串写成const char *
{处理错误
}try
{open();
}catch(文件不存在)
{}catch(文件权限不够)
{}
示例代码:throw抛出的异常必须用try-catch语句来处理
#include <iostream>
#include <algorithm> //算法有关的头文件
#include <vector> using namespace std;/*throw抛出来的异常,必须使用try-catch语句来处理try-catch语句总结成公式try{你要调用的函数,可能会抛出某种异常}catch(你要捕捉的异常类型){捕捉到异常之后,你需要如何处理,把处理的代码写在这里}注意的问题:函数抛出的某种异常,catch后面必须要写上对应的异常类型比如:函数抛出整型异常,catch就要捕捉整型异常try里面的函数调用成功 --》catch不会执行失败,抛出了某种异常 --》catch才会执行
*/
int fun(int n)
{if(n>=0)return 0; //成功elsethrow -1; //抛出整型异常
}
int main()
{try //尝试{//fun(12); //成功,catch不会执行fun(-12); //失败,catch会执行}catch(int n){cout<<"函数调用失败,fun抛出了整型异常,值是: "<<n<<endl;}cout<<"主函数继续往后执行"<<endl;
}
示例代码:一个try可以对应多个catch
#include <iostream>
#include <algorithm> //算法有关的头文件
#include <vector> using namespace std;/*一个try可以对应多个catch(目的:为了处理多个不同类型的异常)C++规定:一个函数可以抛出一种异常类型,也可以抛出多种不同的异常类型
*/int fun(int n)
{if(n>0)return 0; //成功else if(n<0)throw -1; //抛出整型异常elsethrow 6.66; //抛出浮点型异常
}
int main()
{try //尝试{//fun(12); //成功,catch不会执行fun(-12); //失败,catch会执行//fun(0); //失败,catch会执行}catch(int n){cout<<"函数调用失败,fun抛出了整型异常,值是: "<<n<<endl;}catch(double n){cout<<"函数调用失败,fun抛出了浮点型异常,值是: "<<n<<endl;}cout<<"主函数继续往后执行"<<endl;
}
2.C++新增的异常处理方式
2.1 两大类型的异常:
第一种:抛基本数据类型的异常
throw -1; //抛出整型异常
throw 12.5; //抛出浮点型异常
throw “我错了”; //抛出字符串异常
第二种:抛类类型的异常
throw 异常类的对象
C++中定义了一个异常类exception(所有异常的祖先)
class exception
{
public:virtual const char* what() //实现多态做准备{返回异常产生的原因,以字符串的形式返回}
}
class 自定义的异常类:public exception
{
public://重写父类的同名方法what--》多态,必须跟父类的what一模一样,后面的const throw()也要写上const char *what() const throw() //以前的写法const char *what() const noexcept //c++11{}};
示例代码:throw可抛出的几种异常
#include <iostream>
#include <exception>
#include <stdexcept> using namespace std;/*抛类类型的异常第一种情况:直接抛出C++定义的异常类throw 异常类的对象第二种情况:程序员自定义一个异常类,继承exception,然后重写exception的同名虚函数whatvirtual const char* what() const
*/int fun(int n)
{if(n>=0)return 0; //成功else {//创建out_of_range对象out_of_range myerr("我错了,我不该越界");throw myerr;}
}//自定义异常类
class Funerr:public exception
{
public:const char *what(){cout<<"这个是我自定义的异常类"<<endl;return "出错了";}
};int otherfun(int n)
{if(n>=0)return 0; //成功else {//创建自定义异常对象Funerr myerr;throw myerr;}
}
int main()
{try //尝试{//fun(-12); //失败,catch捕捉out_of_range异常otherfun(-55); //失败,catch捕捉Funerr异常}catch(out_of_range &myout){cout<<"函数调用失败,fun抛出了out_of_range异常"<<endl;//打印out_of_range传递过来的信息cout<<"out_of_range传递过来的信息是: "<<myout.what()<<endl;}catch(Funerr &myout){cout<<"函数调用失败,fun抛出了Funerr异常"<<endl;//打印Funerr传递过来的信息cout<<"Funerr传递过来的信息是: "<<myout.what()<<endl;}
}
/*
执行结果:fun(-12); 对应输出函数调用失败,fun抛出了out_of_range异常out_of_range传递过来的信息是:我错了,我不该越界otherfun(-55);对应输出函数调用失败,fun抛出了Funerr异常这个是我自定义的异常类Funerr传递过来的信息是:出错了
*/
几点原则:
- 第一:catch捕捉的异常类型必须跟try中抛出的异常类型一致
- 第二:catch语句可以有多个,分别捕捉不同的错误类型
- 第三:如果函数引发了异常,而没有try块或没有匹配的处理程序时,程序最终将调用abort()函数(终止你的进程)
以下两句话就是abort函数执行打印的
terminate called after throwing an instance of 'char const*'
Aborted (core dumped)
示例代码:利用多态的知识简写
#include <iostream>
#include <exception>
#include <stdexcept> using namespace std;int fun(int n)
{if(n>=0)return 0; //成功else {//创建out_of_range对象out_of_range myerr("out_of_range我错了,我不该越界");throw myerr;}
}//自定义异常类
class Funerr:public exception
{
public:const char *what() const throw() //跟父类的what一模一样{cout<<"这个是我自定义的异常类"<<endl;return "Funerr出错了";}
};int otherfun(int n)
{if(n>=0)return 0; //成功else {//创建自定义异常对象Funerr myerr; //栈空间//Funerr *myerr=new Funerr;throw myerr;}
}
int main()
{try //尝试{//fun(-12); //失败,catch捕捉out_of_range异常otherfun(-55); //失败,catch捕捉Funerr异常}catch(exception &myout) {/*实参和形参关系 exception &myout=myerr父类引用=子类对象*/cout<<"函数调用失败,抛出了异常"<<endl;//打印传递过来的信息cout<<"传递过来的信息是: "<<myout.what()<<endl;}
}/*
执行结果:fun(-12); 对应输出函数调用失败,fun抛出了out_of_range异常out_of_range传递过来的信息是:out_of_range我错了,我不该越界otherfun(-55);对应输出函数调用失败,fun抛出了Funerr异常这个是我自定义的异常类Funerr传递过来的信息是:Funerr出错了
*/
3.异常声明(也叫做异常规范,C++11已经不建议使用了)
-
const char *what() const throw()
//throw()表明该函数不会抛出异常,新的写法用noexcept来代替 -
const char *what() const throw(…) //throw(…)表明该函数会抛出任意类型的异常
-
const char *what() const throw(int) //throw(int)表明该函数会抛出整型异常
-
const char *what() const throw(int,double)
//throw(int,double)表明该函数会抛出整型或者double类型异常
返回值 函数名() noexcept; //函数不会抛出任何异常,C++11新增
示例代码:(…)中省略号的作用
注意: throw(...)使用noexcept(false)代替,表示可抛出任意类型的异常
#include <iostream>
#include <algorithm> //算法有关的头文件
#include <vector> using namespace std;/*省略号的作用:可以匹配任何类型的异常
*/int fun(int n) noexcept(false) //noexcept(false)是异常规范,告知程序员该函数可能会抛出任意类型的异常
{if(n>0 && n<10)return 0; //成功else if(n<0)throw -1; //抛出整型异常else if(n>=10 && n<100)throw 6.66; //抛出浮点型异常elsethrow "字符串异常";
}
int main()
{try //尝试{//fun(12); //成功,catch不会执行fun(-12); //失败,catch会执行//fun(0); //失败,catch会执行}catch(...){cout<<"函数调用失败,fun抛出了随便什么异常,我都能捕捉"<<endl;}cout<<"主函数继续往后执行"<<endl;
}