C++ 异常的详细介绍
C 异常的详解程序有时会遇到运行阶段错误导致程序无法正常执行下去。c异常为处理这种情况提供了一种功能强大的而灵活的工具。异常是相对比较新的C功能有些老编译器可能没有实现。另外有些编译器默认关闭这种特性我们可能需要使用编译器选项来启用它。一、异常机制的使用异常提供了将控制程序的一个部分传递到另一部分的途径。对异常的处理有3个组成部分引发异常使用处理程序捕获异常使用try块示例代码12345678910111213141516171819202122232425262728293031323334353637383940#include stdafx.h#include iostreamdoublehmean(doublea,doubleb);intmain(){doublex, y, z;std::cout Enter two numbers: ;while(std::cin x y) {try{z hmean(x, y);}catch(constchar*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);return0;}doublehmean(doublea,doubleb) {if(a -b) {throwbad hmean() arguments a -b not allowed;}return2.0 *a*b / (a b);}Enter two numbers: 3 6Harmonic mean of 3 and 6 is 4Enter next set of numbers q to quit: 10 -10bad hmean() arguments a -b not allowedEnter anewpair of numbers: qBye!请按任意键继续. . .程序说明try块1234try{z hmean(x, y);}引发异常的代码:1234if(a -b) {throwbad hmean() arguments a -b not allowed;}执行throw语句类似于执行返回语句因为他也将终止函数的执行但throw不是讲控制权返回给调用程序而是导致程序沿函数调用序列后退知道找到包含try块的函数。处理程序(或catch块):12345catch(constchar*s ){std::cout s std::endl;std::cout Enter a new pair of numbers: ;continue;}二、将对象用作异常类型通常引发异常的函数将传递一个对象。这样做的重要优点之一是可以使用不同的异常类型来区分不同的函数在不同情况下引发的异常。另外对象可以携带信息程序员可以根据这些信息来确定引发异常的原因。同时catch块可以根据这些信息来决定采取什么样的措施。示例exc_mean.h1234567891011121314151617181920212223242526272829#include stdafx.h#include iostreamclassbad_hmean{private:doublev1;doublev2;public:bad_hmean(doublea 0,doubleb 0) :v1(a), v2(b) {}voidmesg();};inlinevoidbad_hmean::mesg(){std::cout hmean ( v1 , v2 ) ;invalid argumnents: a -b \n;}classbad_gmean{public:doublev1;doublev2;bad_gmean(doublea 0,doubleb 0) :v1(a), v2(b) {}constchar* mesg();};inlineconstchar* bad_gmean::mesg() {returngmean() arguments shoud be 0 \n;}测试代码:1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071#include stdafx.h#include iostream#include cmath#include exc_mean.hdoublehmean(doublea,doubleb);doublegmean(doublea,doubleb);intmain(){usingstd::cout;usingstd::cin;usingstd::endl;doublex, 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 dont get to play any more .\n ;break;}}cout Bye! \n;system(pause);return0;return0;}doublehmean(doublea,doubleb) {if(a -b)throwbad_hmean(a, b);return2.0 * a*b / (a b);}doublegmean(doublea,doubleb) {if(a 0 || b 0)throwbad_gmean(a, b);returnstd::sqrt(a * b);}输出结果:Enter two numbers 4 12Harmonic mean of 4 and 12 is 6Geometric mean of 4 and 12 is 6.9282Enter next set of numbers q to quit :5 -5hmean ( 5 ,-5) ;invalid argumnents: a -bTry again.5 -2Harmonic mean of 5 and -2 is -6.66667gmean() arguments shoud be 0Value used: 5 ,-2Sorry, you dont get to play any more .Bye!请按任意键继续. . .三、异常规范异常规范是C98的一项功能但c11将其摒弃了。这意味着c11仍然处于标准之中但以后可能会从标准中剔除因此不建议使用它。异常规范示例:12doubleharm(doublea )throw(bad_thing);//可能会抛出 bad_thing异常doublemarm(double)throw() ;//不抛出异常异常规范的作用1、告诉用户可能需要使用try块然而这项功能也可使用注释轻松完成。2、让编译器添加执行运行阶段检查代码检查是否违反了异常规范然而这很难检查例如marm可能不会引发异常但它可能调用一个函数而这个函数调用另一个函数引发了异常总之最好不要使用这项功能c11也建议忽略异常规范然而c11确实支持一种特殊的异常规范可使用关键字noexcept例如1doublemarm() noexcept;四、栈解退假设函数由于异常而不是由于返回)而终止则程序也将释放栈中的内存但不会师范栈的第一个返回地址后停止而是继续释放栈直到找到一个位于Try块的返回地址。随后控制权将转到块尾的异常处理程序而不是函数调用后面的第一条语句。这个过程叫做栈解退。五、exception类较新的C编译器将异常合并到语言中例如为支持该语言exception头文件以前为exception.h 或except.h)定义了 exception类c可以把它用作其他异常类的基类。头文件 exceptionhe 和 stdexcept 定义了一些常用的异常类有logic_error、runtime_error、domain_error 等六、意外异常与未捕获异常处理异常引发后在两种情况下会导致问题。首先如果它是在带异常规范的函数中引发的则必须与规范列表的某种异常匹配在继承层次机构中类类型与这个类与其派生的对象匹配)否则成为意外异常。在默认情况下这将导致程序异常终止虽然C11摒弃了异常规范但仍支持它且有些现有代码使用了它如果异常不是在函数中引发的或者函数没有异常规范则必须捕获它如果没有捕获(在没有try块或没有匹配的catch块时将出现这种情况)则异常被称未捕获异常。这将导致程序异常终止。然而可以修改程序对意外异常和为捕获异常的反应。