福州有网站建设的公司,wordpress分类排版,黄山搜索引擎优化,建一个公司网站C 异常的详解程序有时会遇到运行阶段错误#xff0c;导致程序无法正常执行下去。c异常为处理这种情况提供了一种功能强大的而灵活的工具。异常是相对比较新的C功能#xff0c;有些老编译器可能没有实现。另外#xff0c;有些编译器默认关闭这种特性#xff0c;我们可能需要… C 异常的详解程序有时会遇到运行阶段错误导致程序无法正常执行下去。c异常为处理这种情况提供了一种功能强大的而灵活的工具。异常是相对比较新的C功能有些老编译器可能没有实现。另外有些编译器默认关闭这种特性我们可能需要使用编译器选项来启用它。 一、异常机制的使用 异常提供了将控制程序的一个部分传递到另一部分的途径。对异常的处理有3个组成部分引发异常示例代码#include stdafx.h
#include lt;iostreamgt;
double hmean(double a, double b);
int main()
{ double x, y, z; std::cout lt;lt; Enter two numbers: ; while (std::cin gt;gt; x gt;gt; y) { try { z hmean(x, y); } catch(const char *s ){ std::cout lt;lt; s lt;lt; std::endl; std::cout lt;lt; Enter a new pair of numbers: ; continue; } std::cout lt;lt; Harmonic mean of lt;lt; x lt;lt; and lt;lt; y lt;lt; is lt;lt; z lt;lt; std::endl; std::cout lt;lt; Enter next set of numbers lt;q to quitgt;: ; } std::cout lt;lt; 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 lt;q to quitgt;: 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 lt;lt; s lt;lt; std::endl; std::cout lt;lt; Enter a new pair of numbers: ; continue; }二、将对象用作异常类型 通常引发异常的函数将传递一个对象。这样做的重要优点之一是可以使用不同的异常类型来区分不同的函数在不同情况下引发的异常。另外对象可以携带信息程序员可以根据这些信息来确定引发异常的原因。同时catch块可以根据这些信息来决定采取什么样的措施。 示例 exc_mean.h#include stdafx.h
#include lt;iostreamgt; 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 lt;lt; hmean ( lt;lt; v1 lt;lt; , lt;lt; v2 lt;lt; ) ; lt;lt; 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 gt;0 \n;
}测试代码:#include stdafx.h
#include lt;iostreamgt;
#include lt;cmathgt;
#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 gt;gt; 2; cout lt;lt; Enter two numbers ; while (cin gt;gt; x gt;gt; y) { try { z hmean(x, y); cout lt;lt; Harmonic mean of lt;lt; x lt;lt; and lt;lt; y lt;lt; is lt;lt; z lt;lt; endl; cout lt;lt; Geometric mean of lt;lt; x lt;lt; and lt;lt; y lt;lt; is lt;lt; gmean(x, y) lt;lt; endl; cout lt;lt; Enter next set of numbers lt;q to quit gt;:; } catch (bad_hmean amp; bg) { bg.mesg(); cout lt;lt; Try again. \n; continue; } catch (bad_gmean amp; hg) { cout lt;lt; hg.mesg(); cout lt;lt; Value used: lt;lt; hg.v1 lt;lt; , lt;lt; hg.v2 lt;lt; endl; cout lt;lt; Sorry, you dont get to play any more .\n ; break; } } cout lt;lt; 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 lt; 0 || b lt; 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 lt;q to quit gt;: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 gt;0
Value used: 5 ,-2
Sorry, you dont get to play any more . Bye!
请按任意键继续. . .三、异常规范 异常规范是C98的一项功能但c11将其摒弃了。这意味着c11仍然处于标准之中但以后可能会从标准中剔除因此不建议使用它。 异常规范示例:double harm(double a ) throw(bad_thing);//可能会抛出 bad_thing异常
double marm(double ) throw() ;//不抛出异常异常规范的作用 1、告诉用户可能需要使用try块然而这项功能也可使用注释轻松完成。 2、让编译器添加执行运行阶段检查代码检查是否违反了异常规范然而这很难检查例如marm可能不会引发异常但它可能调用一个函数而这个函数调用另一个函数引发了异常 总之最好不要使用这项功能c11也建议忽略异常规范 然而c11确实支持一种特殊的异常规范可使用关键字noexcept 例如 double marm() noexcept;四、栈解退 假设函数由于异常而不是由于返回)而终止则程序也将释放栈中的内存但不会师范栈的第一个返回地址后停止而是继续释放栈直到找到一个位于Try块的返回地址。随后控制权将转到块尾的异常处理程序而不是函数调用后面的第一条语句。这个过程叫做栈解退。五、exception类 较新的C编译器将异常合并到语言中例如为支持该语言exception头文件以前为exception.h 或except.h)定义了 exception类c可以把它用作其他异常类的基类。 头文件 exceptionhe 和 stdexcept 定义了一些常用的异常类 有logic_error、runtime_error、domain_error 等六、意外异常与未捕获异常处理 异常引发后在两种情况下会导致问题。首先如果它是在带异常规范的函数中引发的则必须与规范列表的某种异常匹配在继承层次机构中类类型与这个类与其派生的对象匹配)否则成为意外异常。在默认情况下这将导致程序异常终止虽然C11摒弃了异常规范但仍支持它且有些现有代码使用了它如果异常不是在函数中引发的或者函数没有异常规范则必须捕获它如果没有捕获(在没有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; //c11
void teminate(); //c98
void teminate() noexcept ; //c11示例:void myQuit()
{ std::cout lt;lt; 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();//c98
unexpected_handle set_unexpected(unexpected_handle f) noexpect;//c11
void unexpected(); c 98
void unexpected() noexcept ;//c 0x使用如下:void myUnexpected() { throw std::bad_exception(); // or just throw ;
}
在程序开始时:lt;brgt;set_unexpected(myUnexpected);我在vs 2015下测试并未实现这种功能必须显示调用terminate() 和 unexpected();完它不仅仅是一个码扫码关注C资源免费送