关于异常和其他

关于异常的几种处理方法:
1、 调用abort()
Abort()函数的原型位于头文件cstdlib.h(或者stdlib.h)中,其典型实现是向标准错误流(即cerr使用的错流),发送abnormal program termination(程序异常终止),然后终止程序。它还返回一个随实现而异的值。
abort()是否刷新文件缓冲区(用于存储读写到文件中的数据的内存区域)取决于实现
但是,也可以使用exit(),该函数刷新文件缓冲区,但不显示信息。

2、 返回错误码
常规错误处理方法,将错误打印出来。

3、 异常机制
异常提供了将控制权从程序的一个部分传递到另一个部分的途径
对异常处理有3个部分组成:

  1. 引发异常
  2. 使用处理程序捕获异常
  3. 使用try块

throw语句实际上是跳转,即命令程序跳转到另一条语句。throw关键字表示引发异常,紧随其后的值指出了异常的特征。
catch关键字表示捕获异常,随后是位于括号中的类型声明,它指出了异常处理程序要响应的异常类型,然后是一个花括号括起的代码块,指出要采取的措施。catch关键字和异常处理类型用作标签,指出当异常被引发时,程序应跳到这个位置执行。
try块标识其中特定的异常可能被激活的代码块,它后面跟一个或多个catch块。Try的后面是一个由花括号括起的代码块,表明需要注意这些代码引起的异常。

Demo1:

#include
using namespace std;

double hmean(double a,double b);

int main()
{
double x, y, z;
cout << “Enter two numbers:” << endl;
while (cin>>x>>y)
{
try
{
z = hmean(x, y);
}
catch (const char* s)
{
cout << s << endl;
cout << “Enter a new pair of numbers:” << endl;
continue;
}
cout << “Harmonic mean of” << x << “and” << y << “is” << z << endl;
cout << “Enter next set of numbers” << endl;

}
cout << "bye!" << endl;
getchar();
return 1;

}

double hmean(double a,double b)
{
if (a == -b)
{
throw “bad hmean() arguments:a = -b not allowed”;
}
return 2.0ab / (a+b);
}
/*
执行throw语句类似于执行返回语句,因为它也将终止函数的执行;
但是throw不是将控制权返回给调用程序,而是导致程序沿函数调用序列后退,直到找到包含try块的函数。

在这个例子中,throw将程序控制权返回给main(),程序将在main()中寻找与引发的异常类型匹配的异常处理程序(位于try块的后面)
出现异常时的程序流程:
1、程序在try块中调用hmean()
2、hmean()引发异常,将从而执行catch块,并将异常字符串赋给s
3、catch返回到while循环开始的位置
*/

Demo2:
将对象用作异常类型

//将对象用作异常类型
#include
using namespace std;

class bad_hmean
{
private:
double v1;
double v2;
public:
bad_hmean(int a = 0, int b = 0) :v1(a), v2(b){}
void mesg();
};
inline void bad_hmean::mesg()
{
cout << “hmean(” << v1 << “,” << v2 << "):invalid arguments: a =- b " << endl;
}

class bad_gmean
{
public:
double v1;
double v2;
bad_gmean(double a = 0, double b = 0) :v1(a), v2(b){}
const char* mesg();

};
inline const char* bad_gmean::mesg()
{
return “gmean() arguments should be>=0”;
}

#include <stdlib.h>
#include
#include “48.cpp”

//函数原型
double hmean(double a,double b);
double gmean(double a,double b);

int main()
{
double x, y, z;
cout << “Enter two numbers:” << endl;
while (cin>>x>>y)
{
try
{
z = hmean(x, y);
cout << “Harmonic mean of” << x << “and” << y << “is” << z << endl;
cout << “Geometric mean of” << x << “and” << y << “is” << gmean(x, y) << endl;
cout << “Enter next set of numbers:”;
}
catch (bad_hmean& bh)
{
bh.mesg();
cout << “Try again” << endl;
continue;
}
catch (bad_gmean& bg)
{
cout << bg.mesg() << endl;
cout << “Values used:” << bg.v1 << “,” << bg.v2 << endl;
cout << “Sorry, you should not get to play any more” << endl;
break;
}
}
cout << “bye!” << endl;

system("pause");
return 1;

}
double hmean(double a,double b)
{
if (a == -b)
{
throw bad_hmean(a,b); //抛出类对象
}
return 2.0ab / (a + b);
}
double gmean(double a,double b)
{
if (a<0 || b<0)
{
throw bad_gmean(a, b);
}
return sqrt(a * b);

}

/*
其他异常特性:
1、控制权返回
2、引发异常时编译器总是创建一个临时拷贝,即使异常规范和catch块中指定的是引用

demo:
class problem{…};

void super() throw(problem)
{

if (ch_no)
{
problem oops;//创建类对象
throw oops; //抛出类对象

}
}


try
{
super();
}
catch(problem& p)
{
//…
}

p将指向oops的副本而不是oops本身,这是件好事,因为函数super()执行完毕后,oops将不复存在。

顺便说一句,将引发异常和创建对象组合在一起将更加简单:
throw problem(); //就是将前面创建类对象的那两句 合并在一起

问题:既然throw语句将生成副本,为何代码中使用引用??
回答:1、基类引用可以执行派生类对象。假设有一组通过继承关联起来的异常类型,
则在异常规范中只需列出一个基类引用,它将与任何派生类对象匹配。

重点:catch块的排列顺序应该与派生类顺序相反
demo:
class bad_1{…};
class bad_2 : public bad_1{…};
class bad_3 : public bad_2{…};


void duper()
{

if(oh_no)
throw bad_1();
if (rats)
throw bad_2();
if (drat)
throw bad_3();

}


try
{
duper();
}
catch(bad_3& b3)
{
}
catch(bad_2& b2)
{
}
catch(bad_1& b1)
{
}

如果将bad_1&处理程序放在最前面,它将捕获bad_1,bad_2,bad_3;通过按相反的顺序排列,bad_3异常将被bad_3处理程序所捕获

提示:如果有一个异常类继承层次结构,应该这样排列catch块:
将捕获位于层次结构最下面的异常类的catch语句放在最前面,
将捕获基类异常的catch语句放在最后面;

如果不知道调用的函数可能引发哪些异常,方法是使用省略号来表示异常类型,从而捕获任何异常。
catch(…) //三个点,捕获任何异常
{
//
}
*/

/*
exception类
#include
代码可以引发exception异常,也可以将exception类用作基类。
有一个名为what()的虚拟成员函数,它将返回一个字符串,该字符串的特征随实现而异。
了解一下,不做延伸
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值