在程序发生异常时,C++提供了专门处理错误的函数。
程序异常终止:
函数abort()
下面的代码假设出现了异常。
return 2.0 * x * y / (x + y);
如果x = -y 那么则调用abort()函数。函数原型位于<cstdio> ,其典型实现是指向标准错误流(即cerr使用的错误流)发送消息,然后终止程序。返回一个随现实而异的值。告诉操作系统,处理失败。也可以使用exit(),但是他不显示消息。
#include <iostream>
using namespace std;
//try,catch,throw
double hmean(double,double);
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 << "answer:" << z << endl;
cout << "Please enter a new pair :" << endl;
}
return 0;
}
double hmean(double x, double y)
{
if(x == -y){
cout << "bad hmean() argument : a = -b not allowed";
abort();
}
return 2.0 * x * y / (x + y);
}
VS2022下
CLion下
可以看见退出代码为 3
异常机制:
#include <iostream>
using namespace std;
//try,catch,throw
double hmean(double,double);
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 << "answer:" << z << endl;
cout << "Please enter a new pair :" << endl;
}
return 0;
}
double hmean(double x, double y)
{
if(x == -y){
throw "bad hmean() argument : a = -b not allowed";
}
return 2.0 * x * y / (x + y);
}
通俗的来说
在调用函数时,程序员可以先尝试一下(try),进入try语句块,看看有没有错误,如果有(需要交给程序员来判断),则抛出一个错误异常类型(throw,通常是一个类),在try语句块下面捕获这个错误(catch,可为多个catch语句块),进行异常处理。
try -> throw -> catch -> error handling
将对象用作异常类型
可以把异常类写成一个单独的头文件
bad_class.h
//
// Created by JAN on 2022/1/27.
//
#ifndef C___BAD_CLASS_H
#define C___BAD_CLASS_H
#include <iostream>
using std::cout;
class bad_hmean
{
private:
double v1;
double v2;
public:
bad_hmean(double a = 0, double b = 0) : v1(a), v2(b) {}
void mesg();
};
inline void bad_hmean::mesg()
{
cout << "调和平均数错误 :" << std::endl
<< "不允许一对相反数为参数" << std::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 "几何平均数计算错误\n";
}
#endif //C___BAD_CLASS_H
main.cpp
#include <iostream>
#include <cmath>
#include "bad_class.h"
using namespace std;
//try,catch,throw
double hmean(double, double);
double gmean(double, double);
int main()
{
double x, y, z;
cout << "Enter two numbers: ";
while (cin >> x >> y){
try{
cout << "调和平均数是:" << hmean(x,y) << endl;
cout << "几何平均数是:" << gmean(x,y) << endl;
}
catch (bad_gmean & g)
{
g.mesg();
cout << "Try again" << endl;
continue;
}
catch (bad_hmean & h)
{
h.mesg();
cout << "Try again" << endl;
continue;
}
}
}
double hmean(double a, double b)
{
if(a == -b){
throw bad_hmean(a,b);//类的构造函数生成临时副本
}else
return 2.0 * a * b / (a + b);
}
double gmean(double a, double b)
{
if(a < 0 || b < 0){
throw bad_gmean(a,b);
}else
return sqrt(a * b);
}
这样做的好处是,可以使用不同的异常类型来区分不同的函数在不同的情况下发生的异常。
运行结果
注意try后面有两个catch语句块,如果第一个catch捕获到了异常,则不会再捕捉第二个。这里涉及到栈解退。详见《C++ Primer Plus》P506~P507.
注意两个错误类的处理方法,一个直接显示错误信息,另一个则返回一个字符串常量。