C++ 異常的詳細(xì)介紹
C++ 異常的詳解
程序有時(shí)會(huì)遇到運(yùn)行階段錯(cuò)誤,導(dǎo)致程序無(wú)法正常執(zhí)行下去。c++異常為處理這種情況提供了一種功能強(qiáng)大的而靈活的工具。異常是相對(duì)比較新的C++功能,有些老編譯器可能沒(méi)有實(shí)現(xiàn)。另外,有些編譯器默認(rèn)關(guān)閉這種特性,我們可能需要使用編譯器選項(xiàng)來(lái)啟用它。
一、異常機(jī)制的使用
異常提供了將控制程序的一個(gè)部分傳遞到另一部分的途徑。對(duì)異常的處理有3個(gè)組成部分:
引發(fā)異常
使用處理程序捕獲異常
使用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! 請(qǐng)按任意鍵繼續(xù). . .
程序說(shuō)明:
try塊:
try { z = hmean(x, y); }
引發(fā)異常的代碼:
if (a == -b) { throw "bad hmean() arguments a= -b not allowed"; }
執(zhí)行throw語(yǔ)句類(lèi)似于執(zhí)行返回語(yǔ)句,因?yàn)樗矊⒔K止函數(shù)的執(zhí)行;但throw不是講控制權(quán)返回給調(diào)用程序,而是導(dǎo)致程序沿函數(shù)調(diào)用序列后退,知道找到包含try塊的函數(shù)。
處理程序(或catch塊):
catch(const char *s ){ std::cout << s << std::endl; std::cout << " Enter a new pair of numbers: "; continue; }
二、將對(duì)象用作異常類(lèi)型
通常,引發(fā)異常的函數(shù)將傳遞一個(gè)對(duì)象。這樣做的重要優(yōu)點(diǎn)之一是,可以使用不同的異常類(lèi)型來(lái)區(qū)分不同的函數(shù)在不同情況下引發(fā)的異常。另外,對(duì)象可以攜帶信息,程序員可以根據(jù)這些信息來(lái)確定引發(fā)異常的原因。同時(shí),catch塊可以根據(jù)這些信息來(lái)決定采取什么樣的措施。
示例:
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"; }
測(cè)試代碼:
#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); } 輸出結(jié)果: 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! 請(qǐng)按任意鍵繼續(xù). . .
三、異常規(guī)范
異常規(guī)范是C++98的一項(xiàng)功能,但c++11將其摒棄了。這意味著c++11仍然處于標(biāo)準(zhǔn)之中,但以后可能會(huì)從標(biāo)準(zhǔn)中剔除,因此不建議使用它。
異常規(guī)范示例:
double harm(double a ) throw(bad_thing);//可能會(huì)拋出 bad_thing異常 double marm(double ) throw() ;//不拋出異常
異常規(guī)范的作用:
1、告訴用戶(hù)可能需要使用try塊,然而這項(xiàng)功能也可使用注釋輕松完成。
2、讓編譯器添加執(zhí)行運(yùn)行階段檢查代碼,檢查是否違反了異常規(guī)范,然而這很難檢查,例如marm可能不會(huì)引發(fā)異常,但它可能調(diào)用一個(gè)函數(shù),而這個(gè)函數(shù)調(diào)用另一個(gè)函數(shù)引發(fā)了異常
總之最好不要使用這項(xiàng)功能,c++11也建議忽略異常規(guī)范
然而c++11確實(shí)支持一種特殊的異常規(guī)范,可使用關(guān)鍵字noexcept
例如
double marm() noexcept;
四、棧解退
假設(shè)函數(shù)由于異常(而不是由于返回)而終止,則程序也將釋放棧中的內(nèi)存,但不會(huì)師范棧的第一個(gè)返回地址后停止,而是繼續(xù)釋放棧,直到找到一個(gè)位于Try塊的返回地址。隨后,控制權(quán)將轉(zhuǎn)到塊尾的異常處理程序,而不是函數(shù)調(diào)用后面的第一條語(yǔ)句。這個(gè)過(guò)程叫做棧解退。
五、exception類(lèi)
較新的C++編譯器將異常合并到語(yǔ)言中,例如,為支持該語(yǔ)言,exception頭文件(以前為exception.h 或except.h)定義了 exception類(lèi),c++可以把它用作其他異常類(lèi)的基類(lèi)。
頭文件 exceptionhe 和 stdexcept 定義了一些常用的異常類(lèi)
有:logic_error、runtime_error、domain_error 等
六、意外異常與未捕獲異常處理
異常引發(fā)后,在兩種情況下,會(huì)導(dǎo)致問(wèn)題。首先,如果它是在帶異常規(guī)范的函數(shù)中引發(fā)的,則必須與規(guī)范列表的某種異常匹配(在繼承層次機(jī)構(gòu)中,類(lèi)類(lèi)型與這個(gè)類(lèi)與其派生的對(duì)象匹配),否則成為意外異常。在默認(rèn)情況下,這將導(dǎo)致程序異常終止(雖然C++11摒棄了異常規(guī)范,但仍支持它,且有些現(xiàn)有代碼使用了它)如果異常不是在函數(shù)中引發(fā)的(或者函數(shù)沒(méi)有異常規(guī)范),則必須捕獲它,如果沒(méi)有捕獲(在沒(méi)有try塊或沒(méi)有匹配的catch塊時(shí),將出現(xiàn)這種情況),則異常被稱(chēng)未捕獲異常。這將導(dǎo)致程序異常終止。然而可以修改程序?qū)σ馔猱惓:蜑椴东@異常的反應(yīng)。
未捕獲異常:
未捕獲異常不會(huì)導(dǎo)致程序立即異常中終止,相反,程序?qū)⑹紫日{(diào)用函數(shù)terminate()。在默認(rèn)情況下terminate()調(diào)用abort()函數(shù)??梢灾付╰erminate()應(yīng)調(diào)用的函數(shù)(而不是abort())來(lái)修改terminate()的這種行為。為此,可調(diào)用set_terminate()函數(shù)。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"); } 在程序開(kāi)始時(shí)執(zhí)行: set_terminate(myQuit);
意外異常
如果發(fā)生意外異常,程序?qū)⒄{(diào)用unexcepted()函數(shù),這個(gè)函數(shù)將調(diào)用teminate(),后者默認(rèn)滴啊用abort()。和set_terminate()函數(shù)一樣,也有一個(gè)可用于修改unexcepted()的行為的set_unexpeceted()函數(shù)。這些函數(shù)也是在頭文件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 ; } 在程序開(kāi)始時(shí):
set_unexpected(myUnexpected);
我在vs 2015下測(cè)試,并未實(shí)現(xiàn)這種功能,必須顯示調(diào)用terminate() 和 unexpected();
如有疑問(wèn)請(qǐng)留言或者到本站社區(qū)交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!
上一篇:c++ 讓程序開(kāi)機(jī)自動(dòng)啟動(dòng)的方法
欄 目:C語(yǔ)言
下一篇:C++中的循環(huán)引用
本文標(biāo)題:C++ 異常的詳細(xì)介紹
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/1186.html
您可能感興趣的文章
- 04-02c語(yǔ)言的正則匹配函數(shù) c語(yǔ)言正則表達(dá)式函數(shù)庫(kù)
- 04-02c語(yǔ)言中對(duì)數(shù)函數(shù)的表達(dá)式 c語(yǔ)言中對(duì)數(shù)怎么表達(dá)
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 04-02C語(yǔ)言中怎么打出三角函數(shù) c語(yǔ)言中怎么打出三角函數(shù)的值
- 01-10c語(yǔ)言求1+2+...+n的解決方法
- 01-10求子數(shù)組最大和的解決方法詳解
- 01-10深入理解約瑟夫環(huán)的數(shù)學(xué)優(yōu)化方法
- 01-10深入二叉樹(shù)兩個(gè)結(jié)點(diǎn)的最低共同父結(jié)點(diǎn)的詳解
- 01-10數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)- 解析最少換車(chē)次數(shù)的問(wèn)題詳解
- 01-10c語(yǔ)言 跳臺(tái)階問(wèn)題的解決方法


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹(shù)的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 04-02c語(yǔ)言函數(shù)調(diào)用后清空內(nèi)存 c語(yǔ)言調(diào)用
- 04-02func函數(shù)+在C語(yǔ)言 func函數(shù)在c語(yǔ)言中
- 04-02c語(yǔ)言的正則匹配函數(shù) c語(yǔ)言正則表達(dá)
- 04-02c語(yǔ)言用函數(shù)寫(xiě)分段 用c語(yǔ)言表示分段
- 04-02c語(yǔ)言中對(duì)數(shù)函數(shù)的表達(dá)式 c語(yǔ)言中對(duì)
- 04-02c語(yǔ)言編寫(xiě)函數(shù)冒泡排序 c語(yǔ)言冒泡排
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 04-02c語(yǔ)言分段函數(shù)怎么求 用c語(yǔ)言求分段
- 04-02C語(yǔ)言中怎么打出三角函數(shù) c語(yǔ)言中怎
- 04-02c語(yǔ)言調(diào)用函數(shù)求fibo C語(yǔ)言調(diào)用函數(shù)求
隨機(jī)閱讀
- 01-10delphi制作wav文件的方法
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 04-02jquery與jsp,用jquery
- 01-10SublimeText編譯C開(kāi)發(fā)環(huán)境設(shè)置
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 01-10C#中split用法實(shí)例總結(jié)
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-11Mac OSX 打開(kāi)原生自帶讀寫(xiě)NTFS功能(圖文