异常,通常是指程序困难检测到的,运行是不正常的情况,例如被0除,数组越界访问等等。
异常处理的语法通常是
try
{
throw()
}
catch()
{
}
关键字try以及它后的大括号中的内容我们称其为try块。简单的说,它包含的是可能会出错的地方(就是我们要检测的地方)。当我们检测到一个错误信息的时候,关键字throw就把这个错误抛出来(强呀:)),抛出来怎么办呢?抛哪去呢?我们的catch关键字就给我们解决掉了这个问题。catch通常用来接收throw抛出来的异常。请注意了,throw抛出来的类型要与catch接受的类型要匹配。就像把一个数字5只能附给一个int型的a一样(当然 int型的b也可以...耳后生风,似乎有砖飞来。。。)
下来,让我来学习一下异常处理的三种用法:
1:常见的异常处理
我们来看下下一段的代码:
#i nclude <iostream>
#i nclude <string>
#i nclude <math.h>
using namespace std;
class triangle //定义一个三角形的类
{
public :
float a,b,c,d; //三角形三边a,b,c,海伦公式常量d
float s; //三角形面积
public:
triangle()
{}
triangle(float a1,float b1,float c1)
{
a=a1;
b=b1;
c=c1;
}
void judgment()//判断是否是三角形
{
string yorn;
if((a+b)<c ||(a+c)<b || (c+b)<a)//任意两边和小于第三边,就不是三角形
{
yorn="不是三角形";
throw(yorn);
}
/*如果任意两边和小于第三边,我们就认为是一个异常(不是三角形,让我算什么呢??),
* 用throw抛出。注意,我们定义了一个string形的变量 yorn(是或不是),并将其抛出
* 。接受的时候也要用string类型来接收。下面就会看到~~*/
}
void dimension()//计算面积
{
d=(a+b+c)/2; //海伦公式
s=sqrt(d*(d-a)*(d-b)*(d-c));
}
};
void main()
{
triangle a(7,2,3);
try
{
a.judgment();
a.dimension();
cout<<"三角形a的面积为: "<<a.s<<endl;
}
//接受了,接受了,请注意,我还是定义了一个 string形的来接受的。
//那么我能不能定义一个int 或别的类型的呢?可以,
//完全可以,只是接受不到罢了:)...又有砖飞来。。。*/
catch (string &err)
{
cout<<err<<endl;
}
}
当然,c++也给提供了一个万能的接收器,
你也可以写成这样
catch(...)
{
cout<<"错了伙计,你知道什么是三角形吗?"<<endl;
}
这里的catch(...)就是一个万能的接收器(别问我为什么,c++规定就是这样写的,就像你不要问我为什么要写这篇文章一样,夜深了,我还在写着...写着...对不起,跑远了,拉回来.)
万能接收器也可以和我写的这个catch放一起用,比如你又可以写成:
try
{
a.judgment();
a.dimension();
cout<<"三角形a的面积为: "<<a.s<<endl;
}
catch (string &err)
{
cout<<err<<endl;
}
catch(...)
{
cout<<"错了伙计,你知道什么是三角形吗?"<<endl;
}
万能接收器要写在最后面。所有catch的最后一个,要么是你定义的catch () (没有万能的),要么是万能的catch(...)
如果你非要写在别的地方,那么。。重写编译器吧。
2:异常规范
当我看着在类中成员函数 void judgment()
{
string yorn;
if((a+b)<c ||(a+c)<b || (c+b)<a)
{
yorn="不是三角形";
throw(yorn);
}
}
时,我的心情澎湃,不能平静。会写抛出了,会写了,我要写两个,删一个留一个。。。等,两个throw,是的我还可以写200个throw,但是我要抛出什么类型呢?目前看来我只想抛出string类型的东西,万一我手快抛错了怎么办(没办法,菜鸟呀,菜鸟总有出错的时候!)。ok,查下资料,喝口小水,看看有没有解决的办法...(翻书中...)
工夫不负我有心人呀,翻出了异常规范这个语法。让我看看是怎么实现的
还是上诉的成员函数,改写成
void judgment() throw(string)
{
string yorn;
if((a+b)<c ||(a+c)<b || (c+b)<a)
{
yorn="不是三角形";
throw(yorn);
}
}
这样,就可以保证我只能抛出string类型的异常。
在函数的参数列表和函数体之间,throw()语句就是一个异常规范。
编译器保证不能抛出在throw()中包含的类型之外的异常。
比如,我们只想在函数中抛出的异常为int,string类型
我们就可以这样写我们的函数
viod myfun(int a,string b) throw(int ,string)
{
//函数实现
......
throw(int类型)
throw(string类型)
throw(char类型)//想抛吗,估计抛不出来的,呵呵~~~~
......
}
这样,就保证我们在函数中只能抛出类型为int,和string的异常。
3:异常和继承
看代码先
#i nclude <iostream>
#i nclude <string>
#i nclude <math.h>
using namespace std;
class triangle :public exception//定义一个三角形的类
{
public :
float a,b,c,d;
float s;
public:
triangle()
{}
triangle(float a1,float b1,float c1)
{
a=a1;
b=b1;
c=c1;
}
void judgment() throw(exception)//判断是否是三角形
{
//任意两边和小于第三边,就不是三角形
if((a+b)<c ||(a+c)<b || (c+b)<a)
{
throw exception("不是三角形,玩我呀大哥");
}
}
void dimension()//计算面积
{
d=(a+b+c)/2; //海伦公式
s=sqrt(d*(d-a)*(d-b)*(d-c));
}
};
void main()
{
triangle a(7,2,3);
try
{
a.judgment();
a.dimension();
cout<<"三角形a的面积为: "<<a.s<<endl;
}
catch(exception &e)
{
cout<<e.what()<<endl;
}
}
上诉代码写的就是异常的继承,triangle继承自exceprion类,exceprion是c++类库的一个标准异常类,triangle类继承了对异常的处理,比如语句throw exception("不是三角形,玩我呀大哥");,这里抛出的是一个exception类型的异常,我们在接受的时候就要用catch (exception &e)来接受,并且使用了一个exption提供的一个what方法,来输入异常描述。
我们也可以不用类库中的exception类,自己来写一个异常处理的类。
下面是我写的一个功能很简单的异常处理类,我把它做为一个基类,用triangle来继承它
#i nclude <iostream>
#i nclude <string>
#i nclude <math.h>
using namespace std;
class exec
{
private:
string error;
public:
exec()
{}
exec(string err)
{
error=err;
}
string geterr()
{
return error;
}
};
class triangle :public exec//定义一个三角形的类
{
public :
float a,b,c,d;
float s;
public:
triangle()
{}
triangle(float a1,float b1,float c1)
{
a=a1;
b=b1;
c=c1;
}
void judgment() throw(exec)//判断是否是三角形
{
//任意两边和小于第三边,就不是三角形
if((a+b)<c ||(a+c)<b || (c+b)<a)
{
throw (exec("不是三角形,你玩我呀大哥"));
}
}
void dimension()//计算面积
{
d=(a+b+c)/2; //海伦公式
s=sqrt(d*(d-a)*(d-b)*(d-c));
}
};
void main()
{
triangle a(7,2,3);
try
{
a.judgment();
a.dimension();
cout<<"三角形a的面积为: "<<a.s<<endl;
}
catch(exec &e)
{
cout<<e.geterr()<<endl;
}
}