C++ 异常的详细介绍
C++ 异常的详解
程序有时会遇到运行阶段错误,导致程序无法正常执行下去。c++异常为处理这种情况提供了一种功能强大的而灵活的工具。异常是相对比较新的C++功能,有些老编译器可能没有实现。另外,有些编译器默认关闭这种特性,我们可能需要使用编译器选项来启用它。
一、异常机制的使用
异常提供了将控制程序的一个部分传递到另一部分的途径。对异常的处理有3个组成部分:
引发异常
使用处理程序捕获异常
使用try块
示例代码:
#include "stdafx.h" #include <iostream> double hmean(double a, double b); int main() { double x, y, z; std::cout << "Enter two numbers: "; while (std::cin >> x >> y) { try { z = hmean(x, y); } catch(const char *s ){ std::cout << s << std::endl; std::cout << " Enter a new pair of numbers: "; continue; } std::cout << "Harmonic mean of " << x << " and " << y << " is " << z << std::endl; std::cout << "Enter next set of numbers <q to quit>: "; } std::cout << "Bye! \n"; system("pause"); return 0; } double hmean(double a, double b) { if (a == -b) { throw "bad hmean() arguments a= -b not allowed"; } return 2.0 *a*b / (a + b); } Enter two numbers: 3 6 Harmonic mean of 3 and 6 is 4 Enter next set of numbers <q to quit>: 10 -10 bad hmean() arguments a= -b not allowed Enter a new pair of numbers: q Bye! 请按任意键继续. . .
程序说明:
try块:
try { z = hmean(x, y); }
引发异常的代码:
if (a == -b) { throw "bad hmean() arguments a= -b not allowed"; }
执行throw语句类似于执行返回语句,因为他也将终止函数的执行;但throw不是讲控制权返回给调用程序,而是导致程序沿函数调用序列后退,知道找到包含try块的函数。
处理程序(或catch块):
catch(const char *s ){ std::cout << s << std::endl; std::cout << " Enter a new pair of numbers: "; continue; }
二、将对象用作异常类型
通常,引发异常的函数将传递一个对象。这样做的重要优点之一是,可以使用不同的异常类型来区分不同的函数在不同情况下引发的异常。另外,对象可以携带信息,程序员可以根据这些信息来确定引发异常的原因。同时,catch块可以根据这些信息来决定采取什么样的措施。
示例:
exc_mean.h
#include "stdafx.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 << "hmean ( " << v1 << " ," << v2 << ") ;" << "invalid argumnents: 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 shoud be >=0 \n"; }
测试代码:
#include "stdafx.h" #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; 1 >> 2; cout << "Enter two numbers "; 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 <q to quit >:"; } catch (bad_hmean & bg) { bg.mesg(); cout << "Try again. \n"; continue; } catch (bad_gmean & hg) { cout << hg.mesg(); cout << "Value used: " << hg.v1 << " ," << hg.v2 << endl; cout << "Sorry, you don't get to play any more .\n "; break; } } cout << " Bye! \n"; system("pause"); return 0; return 0; } double hmean(double a, double b) { if (a == -b) throw bad_hmean(a, b); return 2.0 * a*b / (a + b); } double gmean(double a, double b) { if (a < 0 || b < 0) throw bad_gmean(a, b); return std::sqrt(a * b); } 输出结果: Enter two numbers 4 12 Harmonic mean of 4 and 12 is 6 Geometric mean of 4 and 12 is 6.9282 Enter next set of numbers <q to quit >:5 -5 hmean ( 5 ,-5) ;invalid argumnents: a =-b Try again. 5 -2 Harmonic mean of 5 and -2 is -6.66667 gmean() arguments shoud be >=0 Value used: 5 ,-2 Sorry, you don't get to play any more . Bye! 请按任意键继续. . .
三、异常规范
异常规范是C++98的一项功能,但c++11将其摒弃了。这意味着c++11仍然处于标准之中,但以后可能会从标准中剔除,因此不建议使用它。
异常规范示例:
double harm(double a ) throw(bad_thing);//可能会抛出 bad_thing异常 double marm(double ) throw() ;//不抛出异常
异常规范的作用:
1、告诉用户可能需要使用try块,然而这项功能也可使用注释轻松完成。
2、让编译器添加执行运行阶段检查代码,检查是否违反了异常规范,然而这很难检查,例如marm可能不会引发异常,但它可能调用一个函数,而这个函数调用另一个函数引发了异常
总之最好不要使用这项功能,c++11也建议忽略异常规范
然而c++11确实支持一种特殊的异常规范,可使用关键字noexcept
例如
double marm() noexcept;
四、栈解退
假设函数由于异常(而不是由于返回)而终止,则程序也将释放栈中的内存,但不会师范栈的第一个返回地址后停止,而是继续释放栈,直到找到一个位于Try块的返回地址。随后,控制权将转到块尾的异常处理程序,而不是函数调用后面的第一条语句。这个过程叫做栈解退。
五、exception类
较新的C++编译器将异常合并到语言中,例如,为支持该语言,exception头文件(以前为exception.h 或except.h)定义了 exception类,c++可以把它用作其他异常类的基类。
头文件 exceptionhe 和 stdexcept 定义了一些常用的异常类
有:logic_error、runtime_error、domain_error 等
六、意外异常与未捕获异常处理
异常引发后,在两种情况下,会导致问题。首先,如果它是在带异常规范的函数中引发的,则必须与规范列表的某种异常匹配(在继承层次机构中,类类型与这个类与其派生的对象匹配),否则成为意外异常。在默认情况下,这将导致程序异常终止(虽然C++11摒弃了异常规范,但仍支持它,且有些现有代码使用了它)如果异常不是在函数中引发的(或者函数没有异常规范),则必须捕获它,如果没有捕获(在没有try块或没有匹配的catch块时,将出现这种情况),则异常被称未捕获异常。这将导致程序异常终止。然而可以修改程序对意外异常和为捕获异常的反应。
未捕获异常:
未捕获异常不会导致程序立即异常中终止,相反,程序将首先调用函数terminate()。在默认情况下terminate()调用abort()函数。可以指定terminate()应调用的函数(而不是abort())来修改terminate()的这种行为。为此,可调用set_terminate()函数。set_terminate()和terminate()都是在头文件exception中声明的:
typedef void (*terminate_handle)() ; terminate_handle set_terminate(terminate_handle f) throw();//c++ 98 terminate_handle set_terinate(terminate_handle f) noexcept; //c++11 void teminate(); //c++98 void teminate() noexcept ; //c++11
示例:
void myQuit() { std::cout << "Terminating due to uncaught exception \n"; system("pause"); } 在程序开始时执行: set_terminate(myQuit);
意外异常
如果发生意外异常,程序将调用unexcepted()函数,这个函数将调用teminate(),后者默认滴啊用abort()。和set_terminate()函数一样,也有一个可用于修改unexcepted()的行为的set_unexpeceted()函数。这些函数也是在头文件exception中声明的:
typedef void (* unexpected_handle)(); unexpected_handle set_unexpected(unexpected_handle f) throw();//c++98 unexpected_handle set_unexpected(unexpected_handle f) noexpect;//c++11 void unexpected(); c++ 98 void unexpected() noexcept ;//c+ 0x
使用如下:
void myUnexpected() { throw std::bad_exception(); // or just throw ; } 在程序开始时:
set_unexpected(myUnexpected);
我在vs 2015下测试,并未实现这种功能,必须显示调用terminate() 和 unexpected();
如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
上一篇:c++ 让程序开机自动启动的方法
栏 目:C语言
下一篇:C++中的循环引用
本文标题:C++ 异常的详细介绍
本文地址:https://www.xiuzhanwang.com/a1/Cyuyan/1186.html
您可能感兴趣的文章
- 04-02c语言的正则匹配函数 c语言正则表达式函数库
- 04-02c语言中对数函数的表达式 c语言中对数怎么表达
- 04-02c语言没有round函数 round c语言
- 04-02C语言中怎么打出三角函数 c语言中怎么打出三角函数的值
- 01-10c语言求1+2+...+n的解决方法
- 01-10求子数组最大和的解决方法详解
- 01-10深入理解约瑟夫环的数学优化方法
- 01-10深入二叉树两个结点的最低共同父结点的详解
- 01-10数据结构课程设计- 解析最少换车次数的问题详解
- 01-10c语言 跳台阶问题的解决方法
阅读排行
本栏相关
- 04-02c语言函数调用后清空内存 c语言调用
- 04-02func函数+在C语言 func函数在c语言中
- 04-02c语言的正则匹配函数 c语言正则表达
- 04-02c语言用函数写分段 用c语言表示分段
- 04-02c语言中对数函数的表达式 c语言中对
- 04-02c语言编写函数冒泡排序 c语言冒泡排
- 04-02c语言没有round函数 round c语言
- 04-02c语言分段函数怎么求 用c语言求分段
- 04-02C语言中怎么打出三角函数 c语言中怎
- 04-02c语言调用函数求fibo C语言调用函数求
随机阅读
- 01-10delphi制作wav文件的方法
- 01-11ajax实现页面的局部加载
- 01-10使用C语言求解扑克牌的顺子及n个骰子
- 04-02jquery与jsp,用jquery
- 01-10SublimeText编译C开发环境设置
- 08-05dedecms(织梦)副栏目数量限制代码修改
- 08-05DEDE织梦data目录下的sessions文件夹有什
- 01-10C#中split用法实例总结
- 08-05织梦dedecms什么时候用栏目交叉功能?
- 01-11Mac OSX 打开原生自带读写NTFS功能(图文