C++ 异常处理(一)
来源:互联网 发布:java人脸识别算法代码 编辑:程序博客网 时间:2024/06/06 05:13
例:
计算两个数的调和平均数(两字数字的倒数的平均数的倒数)
表达式为:2.0* x * y / (x + y)
这里x = -y是不允许的,因为上述公式将导致被0除。
方法一:调用 abort() 函数
调用 abort() 函数,需头文件:cstdlib (或 stdlib.h)
其典型实现是向标准错误流(即cerr使用的错误流)发送消息 abnormal program termination (程序异常终止),
然后终止程序。
它还返回一个随实现而异的值,告诉操作系统(如果程序是由另一个程序调用的,则告诉父进程),处理失败。
abort() 是否刷新缓冲区(用于存储读写到文件中的数据的内存区域)取决于实现。
如果愿意,也可以使用 exit() 函数,该函数刷新缓冲区,但不显示消息。
#include <iostream>#include <cstdlib>double hmean(double a, double b);int main(){double x, y, z;std::cout << "Enter two number: ";while (std::cin >> x >> y){z = hmean(x, y);std::cout << "x = " << x << " , " << "y = " << y << " , " << "z = " << z << "\n";std::cout << "Enter next set of numbers <q to quit>: ";}std::cout << "main() function end\n";return 0;}double hmean(double a, double b){if ( a == -b){std::cout << "error in function : hmean()\n";std::abort();//程序在这里中断}return 2.0 * a * b / ( a + b);}注意:hmean()函数中的abort()将直接终止程序,而不是先返回到main().
方法二:返回错误码
该例可以使用指针或引用参数来将值返回给调用程序,并使用函数的返回值来指出成功与否。
#include <iostream>#include <cfloat> // (or float.h) for DBL_MAXbool hmean(double a, double b, double * ans);int main(){double x, y, z;std::cout << "Enter two number: ";while (std::cin >> x >> y){if (hmean(x, y, &z)){std::cout << "x = " << x << " , " << "y = " << y << " , " << "z = " << z << "\n";}else{std::cout << "One value should not be the negative of the other - try again.\n";}std::cout << "Enter next set of numbers <q to quit>: ";}std::cout << "main() function end\n";return 0;}bool hmean(double a, double b, double * ans){if ( a == -b){*ans = DBL_MAX;return false;}else{*ans = 2.0 * a * b / ( a + b);return true;}}这里在hmean()函数中,用函数返回值确定是否成功,用指针参数返回给调用程序。
第三种:异常机制
try,catch,throw
#include <iostream>double hmean(double a, double b);int main(){double x, y, z;std::cout << "Enter two number: ";while (std::cin >> x >> y){try{z = hmean(x, y); //异常可能的区域}catch (const char* s) //这里如果hmean()函数未发生异常,则catch(){}不执行{std::cout << s << std::endl;std::cout << "Enter a new pair of numbers: ";continue;}std::cout << "x = " << x << " , " << "y = " << y << " , " << "z = " << z << "\n";std::cout << "Enter next set of numbers <q to quit>: ";}std::cout << "main() function end, Bye!\n";return 0;}double hmean(double a, double b){if ( a == -b)throw "bad hmean() arguments: a = -b not allowed!"; //如运行到throw,则直接跳到catch,并传递throw的值return 2.0 * a * b / (a + b);}
流程:
执行完try块的中语句,
如果没发生异常,则程序跳过try块后面的catch块,直接执行程序后面的第一条语句。
如果发生异常,则终止hmean()函数的执行,程序往回搜寻发现函数hmean()是从main()中的try块中调用的,因此查找与try{}匹配的catch(){}块,
程序中唯一的一个catch块的参数为char*,因此与它匹配。
程序将throwb出的字符串"bad hmean() arguments: a = -b not allowed!"赋值给变量s, 然后执行程序中的代码。
注意:如果函数发生了异常,而没有try块或没有与之匹配的 catch 块,将会发生什么呢?
在默认情况下:程序将最终调用abort()函数。但我们也可以修改这种行为。
第四:将对象作为异常类型
一般,引发异常的函数将传递一个对象。
优点之一:可以使用不同的异常类型来区分不同的函数在不同的情况下发生的异常。
另外:对象可以携带信息,程序员可以根据这些信息来确定引发异常的原因。
同时:catch 块可以根据这些信息来决定采取什么样的措施。
例:
这里先定义一个异常类,以便生成对象。
//exc_mean.h#include <iostream>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(){std::cout << "bad_hmean: " << v1 << " , " << v2 << " : " << " invalid arguments: a = -b\n";}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\n";}
//error.cpp
#include <iostream>#include <cmath>#include "exc_mean.h"double hmean(double a, double b);double gmean(double a, double b);int main(){using std::cout;using std::cin;using std::endl;double x, y, z;cout << "Enter two numbers: ";while (cin >> x >> y){try{z = hmean(x, y);cout << x << " " << y << " " << z << endl;cout << gmean(x, y) << endl;cout << "Enter next set of numbers <q to quit>: \n";}catch (bad_hmean& bg){bg.mesg();cout << "Try again.\n";continue; //继续循环}catch (bad_gmean& hg){cout << hg.mesg();cout << hg.v1 << " " << hg.v2 << endl;cout << "Sorry, you don't get to play any more.\n";break; //跳出循环}}cout << "Bye!\n";return 0;}double hmean(double a, double b){if (a == -b)throw bad_hmean(a, b); //抛出bad_hmean对象return 2.0 * a * b / (a + b); //a和b的调和平均数}double gmean(double a, double b){if (a < 0 || b < 0)throw bad_gmean(a, b); //抛出bad_gmean对象return std::sqrt(a * b); //a*b的平方根}输出:
Enter two numbers: 4 124 12 66.9282Enter next set of numbers <q to quit>:5 -5bad_hmean: 5 , -5 : invalid arguments: a = -bTry again.5 -25 -2 -6.66667gmean() arguments should be >= 05 -2Sorry, you don't get to play any more.Bye!
第五:
exc_mean.h//代码同上
//error2.cpp
#include <iostream>#include <cmath>#include <string>#include "exc_mean.h"class demo{private:std::string word;public:demo(const std::string& str){word = str;std::cout << "demo: " << word << " created\n";}~demo(){std::cout << "demo: " << word << " destroyed\n";}void show() const{std::cout << "demo: " << word << " showed!\n";}};double hmean(double a, double b);double gmean(double a, double b);double means(double a, double b);int main(){using std::cout;using std::cin;using std::endl;double x, y, z;{demo d1("found in block in main()");cout << "Enter two numbers: ";while (cin >> x >> y){try{z = means(x, y);cout << x << " " << y << " " << z << endl;cout << "Enter next set of numbers <q to quit>: \n";}catch (bad_hmean& bg){bg.mesg();cout << "Try again.\n";continue; //继续循环}catch (bad_gmean& hg){cout << hg.mesg();cout << hg.v1 << " " << hg.v2 << endl;cout << "Sorry, you don't get to play any more.\n";break; //跳出循环}}}cout << "Bye!\n";cin.get();cin.get();return 0;}double hmean(double a, double b){if (a == -b)throw bad_hmean(a, b); //抛出bad_hmean对象return 2.0 * a * b / (a + b); //a和b的调和平均数}double gmean(double a, double b){if (a < 0 || b < 0)throw bad_gmean(a, b); //抛出bad_gmean对象return std::sqrt(a * b); //a*b的平方根}double means(double a, double b){double am, hm, gm;demo d2("found in means()");am = (a + b) / 2.0;try{hm = hmean(a, b); //如果异常,将先触发means中的catch块,再触发main中的catch块gm = gmean(a, b); //如果异常,means中将无法处理,这时异常被传递给main()中的相应的catch块}catch(bad_hmean& bg) //这里的catch块触发后,将会再触发main()中的{bg.mesg();std::cout << "caught in means()\n";throw; //rethrow the exception //当这里发生异常时,仍然为d2调用了析构函数 //原因估计是thow完,运行至catch块},后直接至means函数块的},这时触发了d2的析构}d2.show();return (am + hm + gm) / 3.0;}
输出:
demo: found in block in main() createdEnter two numbers: 6 12demo: found in means() createddemo: found in means() showed!demo: found in means() destroyed6 12 8.49509Enter next set of numbers <q to quit>:6 -6demo: found in means() createdbad_hmean: 6 , -6 : invalid arguments: a = -bcaught in means()demo: found in means() destroyedbad_hmean: 6 , -6 : invalid arguments: a = -bTry again.6 -8demo: found in means() createddemo: found in means() destroyedgmean() arguments should be >= 06 -8Sorry, you don't get to play any more.demo: found in block in main() destroyedBye!
- C#中的异常处理(一)
- C#中的异常处理(一)
- C#中的异常处理(简单)一
- c语言实现异常处理 一
- C&&C++的异常处理(一)
- C++中的异常处理(一)——C和C++中异常处理的区别
- C#异常处理一
- AOP异常处理一
- Java异常处理 一
- java 异常处理(一)
- C++异常处理(一)
- 异常处理(一)
- C++ 异常处理(一)
- Java异常处理一
- (一)异常处理
- 异常处理(一)
- c#中的异常处理
- 异常处理 - [C++]
- STL学习之--非类型模板参数
- MyISAM和InnoDB的区别的粗略理解
- C指针
- IDEA Intellij开启自动make
- 支持向量机(四)
- C++ 异常处理(一)
- 使用代码修改网页内容
- hdu 1671 Phone List 字典树(静态版)
- 写两个线程,其中一个线程打印1-52,另一个打印A-Z,打印顺序为12A34B56C....5152Z。(《疯狂java讲义》第12章课后题一)
- 斐波拉契数列性质
- Netty系列之Netty百万级推送服务设计要点
- 第四周项目二 分数类的雏形
- ubuntu12.04 N卡双显卡 解决方案
- ironic pxe