国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C++ > 正文

C++ 異常的詳細介紹

2020-01-26 13:55:51
字體:
來源:轉載
供稿:網友

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 6Harmonic mean of 3 and 6 is 4Enter next set of numbers <q to quit>: 10 -10bad hmean() arguments a= -b not allowed Enter a new pair of numbers: qBye!請按任意鍵繼續. . .

程序說明:

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 12Harmonic 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 -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 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++ 98terminate_handle set_terinate(terminate_handle f) noexcept; //c++11void teminate(); //c++98void 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++98unexpected_handle set_unexpected(unexpected_handle f) noexpect;//c++11void unexpected(); c++ 98void unexpected() noexcept ;//c+ 0x

使用如下:

void myUnexpected() {  throw std::bad_exception(); // or just throw ;}在程序開始時:
set_unexpected(myUnexpected);

我在vs 2015下測試,并未實現這種功能,必須顯示調用terminate() 和 unexpected();

如有疑問請留言或者到本站社區交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 海宁市| 大安市| 苏州市| 门源| 禄丰县| 晴隆县| 郴州市| 新巴尔虎左旗| 梅河口市| 通化县| 河池市| 渝北区| 孟村| 孟津县| 炎陵县| 峡江县| 柘城县| 望奎县| 黄大仙区| 湖州市| 来宾市| 镇远县| 云林县| 梁河县| 正定县| 郧西县| 云梦县| 兴国县| 新乡县| 富锦市| 潜山县| 镇赉县| 罗江县| 芦溪县| 宜都市| 尚志市| 潞城市| 乾安县| 藁城市| 炉霍县| 柳江县|