异常
一、异常的概述
- 程序有时会遇到运行阶段错误,导致程序无法正常的运行下去。
- 例如:程序可能试图打开一个不可用的文件,请求过多的内存,或者遭到不能容忍的值。
- 通常,程序员都会试图预防这种意外情况。所以c++出现了异常的功能。
1.基本方法
讨论异常之前,了解可使用的一些基本方法,例:计算两个的调和平均数的函数为例。两个数的调和平均数的定义是:这两个数字倒数的平均值的倒数。表达式:2.0xy/(x+y)
如果y是x的负值,则上述公式将导致被零除:这是不允许的运算。对于被零的情况,编译器将生成一个表示无穷大的特殊浮点值,cout将这种值显示为Inf,inf,INF或类似的东西。程序也可能会崩溃。
2.调用abort()
- 对于上面的情况,处理方法之一,若参数是另一个参数的负值,调用abort()函数。
- 函数头文件
cstdlib(stdlib.h)
,实现是向标准错误流(即cerr使用的错误流)发送信息: 程序异常终止,返回随实现而异的值,处理失败。 abotr()
是否刷新文件缓冲区取决于实现。也可以使用exit()
,该函数刷新缓冲区,不显示信息。
实例:
#include <iostream>
#include<cstdlib>
using namespace std;
double hmean(double a,double b);
int main()
{
double x,y,z;
cout<<"Enter two numbers:";
while(cin>>x>>y)
{
z=hmean(x,y);
cout<<"Harmonic mean of"<<x<<"and"<<y
<<"is"<<z<<end;
cout<<"Enter next set of number <q to quit>:";
}
cout<<"Bye!\n";
return 0;
}
double hmean(double a, double b)
{
if(a==-b)
{
cout<<"unenable arguments to hmean()\n";
abort();//调用将直接终止程序,不是返回到main()
}
return 2.0*a*b/(a+b);
}
为了避免异常终止,程序应在调用hmean()
函数之前检查x和y
的值。
二、返回错误码
- 一种比异常终止更灵活的方法:使用函数的返回值来指出问题。
- 如:
ostream类的get(void)
成员返回下一个输入字符的ASCII码,但到达文件尾时,将返回特殊值EOF。 - 对于
hmean()
不管用,任何数值都是有效的返回值,因此不存在可用于指出问题的特殊值。 - 这时,可以使用指针参数或引用参数来将值返回给调用程序,并使用函数的返回值来指出成功还是失败。
istream
族重载>>
运算符使用了这种技术的变体。使得程序采取除异常终止程序之外的其他措施。
例:将hmean()
的返回值重新定义为bool
,让返回值指出成功了还是失败。例:
#include <iostream>
#include<cfloat>
using namespace std;
bool hmean(double a,double b, double * ans);
int main()
{
double x,y,z;
cout<<"Enter two numbers:";
while(cin>>x>>y)
{
if(hmean(x,y,&z))
cout<<"Harmonic mean of"<<x<<"and"<<y
<<"is"<<z<<endl;
else
cout<<"one value should not be the negative"
<<"of theother-try again'\n";
cout<<"Enter next set of numbers <q to quit>:";
}
cout<<"Bye!\n";
return 0;
}
bool hmean(double a, double b,double * ans)
{
if(a==-b)
{
*ans=DBL_MAX;
return false;
}
else
{
return 2.0*a*b/(a+b);
return true;
}
}
三、异常机制
异常的组成部分:
- 引发异常;
- 使用处理程序捕获异常;
- 使用try块;
程序在出现问题时将引发异常。
例如:可以修改hmean()
,而不是调用abort()
函数,throw语句实际上是跳转,即命令程序跳到另一条语句。
throw关键字表示引发异常,紧随后的值(例如字符串或对象)指出了异常的特征。
- 程序使用异常处理程序来捕获异常,异常处理程序位于要处理问题的程序中,catch关键字表示捕获异常。
- 处理程序以关键字catch开头,随后是位于括号中的类型声明,它指出了异常处理程序要响应的异常类型;
- 花括号括起的代码块,指出要采取的措施。
- catch关键字和异常类型用作标签,指出当异常被引发时,程序应调到这个位置执行。异常处理程序也被称catch块。
- try标识其中特定的异常可能被激活的代码块,try的后面是一个由花括号括起来的代码块,表明需要注意这些代码引发的异常。
例:
#include <iostream>
using namespace std;
double hmean(double a,double b);
int main()
{
double x,y,z;
cout<<"Enter two numbers:";
while(cin>>x>>y)
{
//捕获开始
try{
z=hmean(x,y);
}//捕获结束
catch(const char * s)//异常处理开始
{
cout<<s<<endl;
cout<<"Enter a new pair of numbers:";
continue;
}//异常处理结束
cout<<"Harmonic mean of"<<x<<"and"<<y
<<"is"<<z<<endl;
cout<<"Enter next set of numbers <q to quit>:";
}
cout<<"Bye!\n";
return 0;
}
double hmean(double a, double b)
{
if(a==-b)
throw "bad hmean() arguments:a=-b not allowed";//抛出异常,throw将程序控制权返回给main()。
return 2.0*a*b/(a+b);
}
-
1-10传递给函数,if语句导致
hmean()
引发异常。这将终止hmean()
的执行。 -
hmean()
函数是从main()
中的try
块中调用的,因此查找与异常类型匹配的catch
块。 -
唯一的一个catch块的参数