C++提供了一种错误处理机制:异常。
异常的基本思想是:如果一个函数发现一个自己不能处理的错误,它不是正常返回,而是抛出(throw)一个异常来表示错误的发生。任一个直接或间接的函数调用者都可以捕捉到这一异常,并确定应该如何处理。函数可以用try语句来处理异常:把所要处理的异常情况罗列在catch语句后。如果出现一个没有被任何调用函数处理的异常,程序终止运行。
1.参数错误
class Bad_area{}; //一个专门报告area()错误的类
//计算矩形面积
//在参数错误时抛出Bad_area异常
int area(int length, int width)
{
if(length <= 0 || width <= 0) throw Bad_area{};
return length*width;
}
需要注意的是Bad_area{}表示“创建一个Bad_area类型的缺省值对象”。因此throw Bad_area{}表示“创建一个Bad_area类型的对象并抛出它”。
现在我们可以这样写:
int main()
{
try{
int x=-1;
int y=2;
int z=4;
//...
int area1 = area(x, y);
int area2 = framed_area(1, z);
int area3 = framed_area(y, z);
double ratio = area1/area3;
}
catch(Bad_area)
{
cout << "Oops! bad arguments to area()\n";
}
}
对于简单程序来说在main()中捕捉runtime_error更理想:
int main()
try{
//... 我们的程序 ...
return 0;
}catch(runtime_error& e)
{
cerr<<"runtime error:"<<e.what()<<'\n';
keep_window_open();
return 1;
}
或者对异常进行一些通用处理:
int main()
try{
//我们的程序
return 0; //0表示成功
}
catch(exception& e)
{
cerr<<"error: "<<e.what()<<'\n';
keep_window_open();
return 1; //1表示失败
}
catch(...){
cerr<<"Oops: unknown exception!\n";
keep_window_open();
return 2; //2表示失败
}
这里我们加上catch(...)来处理任何其他类型的异常。
前置条件助于我们避免设计错误和及早发现使用错误。
int my_complicated_function(int a, int b, int c)
//参数为正数且a<b<c
{
if(!(0<a && a<b && b<c))
{
error("bad arguments for mcf");
}
//...
}
我们可以对函数的后置条件进行一部分的检查:
int area(int length, int width)
//计算矩形的面积
//前置条件:长度和宽度是正数
//后置条件:返回值是正数,表示矩形面积
{
if(length<=0 || width<=0) error("area() pre-condition");
int a = length * width;
if(a<=0) error("area() post-condition");
return a;
}