参考《C++ Primer 第五版》P172
一、throw表达式
一个简单的例子:
#include <iostream>
using namespace std;
int main()
{
int a=5,b=0;
if(b==0)
throw b; //抛出异常
return 0;
}
//output:
terminate called after throwing an instance of 'int'
C++标准库定义了一组类,用于报告标准库函数遇到的问题。其中 exception 头文件定义了最通用的异常类 exception。它只报告异常的发生,不能提供任何额外信息。示例如下:
#include <iostream>
using namespace std;
int main()
{
int a=5,b=0;
if(b==0)
throw exception();
return 0;
}
//output:
terminate called after throwing an instance of 'std::exception'
what(): std::exception
可以看到 exception 只能提供系统的报错信息,那么如何添加自己写的错误信息呢?可以用 头文件定义的其他异常类,比如 runtime_error,表示只有在运行时才能检测出的问题。示例如下:
#include <iostream>
using namespace std;
int main()
{
int a=5,b=0;
if(b==0)
throw runtime_error("Error: b=0");
return 0;
}
//output:
terminate called after throwing an instance of 'std::runtime_error'
what(): Error: b=0
在控制台输出了自己添加的报错语句:Error: b=0,其中 what() 是C++异常类型唯一定义的成员函数,该函数没有任何参数,返回值是一个 const char* 的字符串。
二、try语句块(try–catch语句)
使用ry语句块时,C++异常处理的流程为:
throw(抛出异常)–> try(检测异常) --> catch(捕获异常)
异常必须显式地抛出(throw),才能被检测(try)和捕获(catch)到;如果没有显式的抛出,即使有异常也检测不到。
所以必须使用 throw 关键字来显式地抛出异常,并且用catch捕获异常时,catch和throw的数据类型必须一致,否则无法捕获异常。
try语句块的格式为:
try {
...
}
catch (...) {
...
}
需要注意的是try之后可以跟多个catch子句,而不止一个。
用法示例:
#include <iostream>
using namespace std;
//整数相除
double func(int a,int b){
if(b==0)
throw b; //抛出异常,数据类型为 int
double res=static_cast<double>(a)/b; //数据类型转换
return res;
}
int main()
{
int a=5,b=3,c=0;
try
{
double result=func(a,b); //没有异常
cout<<a<<"/"<<b<<"= "<<result<<endl;
result=func(a,c); //有异常
}
catch (int) //捕获异常
{
cerr<<"Error: c=0"<<endl; //cerr是标准错误流,用于输出错误信息
}
return 0;
}
//output:
5/3= 1.66667
Error: c=0
其中的 catch (int)表示捕获 throw 抛出的数据类型为 int 的异常。
当然throw可以以抛出其他数据类型的异常,我们稍作修改,将 throw b 修改为 throw “Error: b=0”,相应的catch也需要作出修改,代码如下:
#include <iostream>
using namespace std;
//整数相除
double func(int a,int b){
if(b==0)
throw "Error: b=0"; //抛出异常,数据类型为what()成员函数的返回值类型 const char*
double res=static_cast<double>(a)/b; //数据类型转换
return res;
}
int main()
{
int a=5,b=3,c=0;
try
{
double result=func(a,b); //没有异常
cout<<a<<"/"<<b<<"= "<<result<<endl;
result=func(a,c); //有异常
}
catch (const char*) //捕获异常
{
cerr<<"Error: c=0"<<endl;
}
return 0;
}
//output:
5/3= 1.66667
Error: c=0
这样可能会感觉比较麻烦,因为我们需要确定 throw抛出的异常的数据类型。有一种更见的方法是使 throw 抛出异常类,比如:
throw runtime_error(“Error: b=0”);
catch (runtime_error)
这样 catch 只需要捕获 runtime_error即可。
代码示例:
#include <iostream>
using namespace std;
//整数相除
double func(int a,int b){
if(b==0)
throw runtime_error("Error: b=0"); //抛出runtime_error异常
double res=static_cast<double>(a)/b;
return res;
}
int main()
{
int a=5,b=3,c=0;
try
{
double result=func(a,b); //没有异常
cout<<a<<"/"<<b<<"= "<<result<<endl;
result=func(a,c); //有异常
}
catch (runtime_error) //捕获异常
{
cerr<<"Error: c=0"<<endl;
}
return 0;
}
//output:
5/3= 1.66667
Error: c=0