一.异常
异常是指存在于代码运行时的反常行为,这些反常行为超出了函数正常执行功能的范围,异常处理机制包括两部分的协同支持:异常检测和异常处理
二.C++中的异常处理
在c++语言中,异常处理包括:
- throw 表达式(throw expression):异常检测部分使用throw表达式来表示它遇到了无法处理的问题
- try 语句块(try block):try语句块用来处理异常,try语句块以关键字try开始,以一个或多个catch子句结束,try语句块中代码抛出的异常通常会被某个catch子句处理
- 一套异常类(exception class):用于在throw表达式和相关的catch子句之间传递异常的具体信息
2.1 throw表达式
举例:输入两个整数变量值,判断是否相等
int a,b;
cin>>a>>b;
if(a==b){
cout<<"equal"<<endl;
}else{
cout<<"not equal,please input again"<<endl;
}
我们暂时把不相等作为一种异常,把输出不相等的信息作为与用户的交互,在真实的程序中,应该把代码正常执行和与用户的交互分离开,即在不相等时抛出异常:
if(a!=b){
throw runtime_error("not equal,please input again"); //随机选取的异常类型
}
cout<<"equal"<<endl; //若程序执行到这一句表示程序没有异常
具体的异常类型分类和异常类型后面括号内跟随的表达式的意义会在文章第三部分讲解
在该程序中,若a和b不相等,就会抛出一个runtim_error类型的异常,抛出异常将终止当前的函数,并把控制权转移给能处理该异常的代码
2.2 try语句块
try语句块通常的语法格式:
try {
program-statements
} catch (exception-declaration) {
handler-statements
} catch (exception-declaration) {
handler-statements
} ...
try语句块内如果出现了异常,选中了某个catch子句处理异常,执行对应的块,执行完该块后,跳转到最后一个catch子句后的那一句继续执行
try语句块中的program-statements组成程序正常的逻辑,可以包括声明在内的任意c++语句,但try语句块内声明的变量在外部无法访问,即使在catch子句内也无法访问
cin>>a>>b;
try{
if(a!=b){
throw runtime_error("not equal,please input again");
}
cout<<"equal"<<endl;
} catch (runtime_error err){
cout<<err.what()<<"\ntry again? enter y or n"<<endl;
}
由于此程序中,try语句抛出的异常类型和catch异常声明的类型一致,即为匹配到了catch子句,在正式程序中,可能会没有匹配到catch子句,此时程序会转到terminate的标准库函数,terminate会终止当前进程的执行
三.标准异常
C++标准库定义了一组类,用于报告标准库函数遇到的问题,他们分别定义在4个头文件中:
- exception头文件定义了最通用的异常类exception,只报告异常的发生,不提供任何额外信息
- stdexcept头文件定义了几种常用的异常类:exception,runtime_error,range_error(结果超过值域),overflow_error,underflow_error,logic_error,domain_error(参数对应的结果值不存在),invailid_argument,length_error,out_of_range
- new头文件定义了bad_alloc异常类型
- type_info头文件定义了bad_cast异常类型
只能以默认初始化的方式初始化exception,bad_alloc,bad_cast对象,不允许为这些对象提供初始值,其他异常类型(主要指stdexcept头文件中的异常类型)则相反,应该用string对象或者C风格字符串初始化这些类型的对象,但不允许使用默认初始化的方式,且创建此类对象时,要提高初始值,如上面写的 throw runtime_error("not equal,please input again"); 该句创建了一个runtime_error类型的对象,初始值为"not equal,please input again",异常类型只定义了一个what()成员函数,该函数没有参数,返回值是一个C风格字符串,用于提供关于异常的文本信息,一般返回的是初始化该类型对象的初始值,如上面语句返回"not equal,please input again"。