概述
除数不能为0、索引数组元素不能为空、指针不能过界……
最典型的异常处理方式是用if树做分支处理,剔除错误的路线
#include <iostream>
using namespace std;
int main(){
int number1,number2;
if(number2!=0){
cout<<(number1/number2)<<endl;
}
else{
cout<<"Divisor cannot be zero"<<endl;
}
return 0;
}
C++引入了异常处理机制。基本思想是:函数 A 在执行过程中发现异常时可以不加处理,而只是“拋出一个异常”给 A 的调用者,假定为函数 B。
即“创建、抛出、获取和处理 ”一个异常。
#include <iostream>
using namespace std;
int main(){
int number1,number2;
try{
if(number2==0)
throw number1;
cout<<(number1/number2)<<endl;
}
catch(int ex){
cout<<ex<<"Divisor cannot be zero"<<endl;
}
return 0;
}
- 正常情况下,
try
块是应该运行的代码 throw
就是异常信号,出现了这个就说明出现异常了,那么就带着“异常”抛出- “异常”被
catch
接收,当出现异常时执行catch块,执行过后执行catch块的下一个语句;不出现时不执行catch块
可以满足多个catch块,抛出的异常需要满足相对应catch块的接收类型才可执行,若接收不到相应类型,也就是说异常得不到处理,那么程序就立即中止
可以捕获任何异常的块:catch(...){}
如果对异常参数不感兴趣,也可以不写catch块参数
异常抛出机制
如果一个函数在执行过程中拋出的异常在本函数内就被 catch 块捕获并处理,那么该异常就不会拋给这个函数的调用者(也称为“上一层的函数”);如果异常在本函数中没有被处理,则它就会被拋给上一层的函数。
#include <iostream>
using namespace std;
int quotient(int number1,int number2){
if(number2==0)
throw number1;
return number1/number2;
}
int main{
int number1,number2;
cin>>number1>>number2;
try{
int result=quotient(number1,number2);
cout<<result<<endl;
}
catch(int ex){
cout<<ex<<endl;
}
return 0;
}
可见函数quotient
抛出了异常,但函数本身并没有能接收的catch
。但主函数中有。如果本函数没找到相应catch
,那么就会返回上一级调用函数。
这样的话处理异常就会非常方便,大程序中层层调用的小函数往往没有自己处理异常的能力(尤其是库函数),这个能力交给大函数统一处理更加方便
如果拋出的异常是派生类的对象,而 catch 块的异常类型是基类,那么这两者也能够匹配,因为派生类对象也是基类对象。
throw
写在catch
内,这个叫做“重抛出异常”,这个时候异常被抛给调用者,用于无法处理异常或者想通知调用者发生了这么一个异常的情况
tips:
函数的异常声明列表
void func() throw (int, double, A, B, C);
void func() throw (int, double, A, B, C){...}
只是为了增强可读性,编译器一般也不会管他
异常类
一个异常其实往往需要抛出更多需要的信息,一个int类肯定远远不止。C++预定了很多可用于创建异常对象的类。
exception
根类包含一个虚函数what()
,返回一个异常对象的错误信息runtime_error
类是多个描述运行错误的标准异常类的基类,类overflow_error
描述算数太大溢出,类underflow_error
描述太小溢出logic_error
类是多个描述逻辑错误的标准异常类的基类,类length_error
描述对象大小超过最大允许长度的错误,类out_of_range
描述值超出允许范围的错误bad_alloc
,bad_cast
,bad_typeid
和bad_exception
类描述C++运算符抛出的异常。其中bad_alloc
对应new
运算符无法分配内存,bad_cast
对应dynamic_cast
在转换引用类型发生错误时的溢出,bad_typeid
对应typeid
在运算对象为空指针时抛出,bad_exception
描述了从未遇到的异常
#include <iostream>
using namespace std;
int quotient(int number1,int number2){
if(number2==0)
throw runtime_error("Divisor cannot be zero");
return number1/number2;
}
int main{
int number1,number2;
cin>>number1>>number2;
try{
int result=quotient(number1,number2);
cout<<result<<endl;
}
catch(runtime_error& ex){
cout<<ex.what()<<endl;
}
return 0;
}
//太深入的自定义类再学就消化不良了,先留个todo