c++ try catch
生活随笔
收集整理的這篇文章主要介紹了
c++ try catch
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
開發程序是一項“燒腦”的工作,程序員不但要經過長期的知識學習和思維訓練,還要做到一絲不茍,注意每一個細節和邊界。即使這樣,也不能防止程序出錯。
專家指出,長期作息不規律 + 用腦過度的危害很大,可能會誘發神經衰弱、失眠等疾病。我就是受害者之一,曾被失眠困擾了好幾年,不但入睡困難,還容易早醒。程序員要注意勞逸結合,多去健身房,多跑步,多打球,多陪女朋友旅游等,千萬不要熬夜,以為深夜寫代碼效率高,這樣會透支年輕的身體。
程序的錯誤大致可以分為三種,分別是語法錯誤、邏輯錯誤和運行時錯誤:
1) 語法錯誤在編譯和鏈接階段就能發現,只有 100% 符合語法規則的代碼才能生成可執行程序。語法錯誤是最容易發現、最容易定位、最容易排除的錯誤,程序員最不需要擔心的就是這種錯誤。
2) 邏輯錯誤是說我們編寫的代碼思路有問題,不能夠達到最終的目標,這種錯誤可以通過調試來解決。
3) 運行時錯誤是指程序在運行期間發生的錯誤,例如除數為 0、內存分配失敗、數組越界、文件不存在等。C++ 異常(Exception)機制就是為解決運行時錯誤而引入的。
運行時錯誤如果放任不管,系統就會執行默認的操作,終止程序運行,也就是我們常說的程序崩潰(Crash)。 C++ 提供了異常(Exception)機制,讓我們能夠捕獲運行時錯誤,給程序一次“起死回生”的機會,或者至少告訴用戶發生了什么再終止程序。
【例1】一個發生運行時錯誤的程序:#include <iostream> #include <string> using namespace std;
int main(){ string str = "http://c.biancheng.net"; char ch1 = str[100]; //下標越界,ch1為垃圾值 cout<<ch1<<endl; char ch2 = str.at(100); //下標越界,拋出異常 cout<<ch2<<endl; return 0; }
運行代碼,在控制臺輸出 ch1 的值后程序崩潰。下面我們來分析一下原因。
at() 是 string 類的一個成員函數,它會根據下標來返回字符串的一個字符。與 [ ]不同,at() 會檢查下標是否越界,如果越界就拋出一個異常;而 [ ]不做檢查,不管下標是多少都會照常訪問。 所謂拋出異常,就是報告一個運行時錯誤,程序員可以根據錯誤信息來進一步處理。 上面的代碼中,下標 100 顯然超出了字符串 str 的長度。由于第 6 行代碼不會檢查下標越界,雖然有邏輯錯誤,但是程序能夠正常運行。而第 8 行代碼則不同,at() 函數檢測到下標越界會拋出一個異常,這個異常可以由程序員處理,但是我們在代碼中并沒有處理,所以系統只能執行默認的操作,也即終止程序執行。
這就好比,catch 告訴 try:你去檢測一下程序有沒有錯誤,有錯誤的話就告訴我,我來處理,沒有的話就不要理我!
catch 關鍵字后面的 exceptionType variable指明了當前 catch 可以處理的異常類型,以及具體的出錯信息。我們稍后再對異常類型展開講解,當務之急是演示一下 try-catch 的用法,先讓讀者有一個整體上的認識。
【例2】修改上面的代碼,加入捕獲異常的語句:#include <iostream> #include <string> #include <exception> using namespace std;
int main(){ string str = "http://c.biancheng.net"; try{ char ch1 = str[100]; cout<<ch1<<endl; }catch(exception e){ cout<<"[1]out of bound!"<<endl; }
try{ char ch2 = str.at(100); cout<<ch2<<endl; }catch(exception &e){ //exception類位于<exception>頭文件中 cout<<"[2]out of bound!"<<endl; }
return 0; }
運行結果:
(
[2]out of bound!
可以看出,第一個 try 沒有捕獲到異常,輸出了一個沒有意義的字符(垃圾值)。因為 [ ]不會檢查下標越界,不會拋出異常,所以即使有錯誤,try 也檢測不到。 換句話說,發生異常時必須將異常明確地拋出,try 才能檢測到;如果不拋出來,即使有異常 try 也檢測不到。所謂拋出異常,就是明確地告訴程序發生了什么錯誤。
第二個 try 檢測到了異常,并交給 catch 處理,執行 catch 中的語句。需要說明的是,異常一旦拋出,會立刻被 try 檢測到,并且不會再執行異常點(異常發生位置)后面的語句。本例中拋出異常的位置是第 17 行的 at() 函數,它后面的 cout 語句就不會再被執行,所以看不到它的輸出。
說得直接一點,檢測到異常后程序的執行流會發生跳轉,從異常點跳轉到 catch 所在的位置,位于異常點之后的、并且在當前 try 塊內的語句就都不會再執行了;即使 catch 語句成功地處理了錯誤,程序的執行流也不會再回退到異常點,所以這些語句永遠都沒有執行的機會了。本例中,第 18 行代碼就是被跳過的代碼。
執行完 catch 塊所包含的代碼后,程序會繼續執行 catch 塊后面的代碼,就恢復了正常的執行流。
為了演示「不明確地拋出異常就檢測不到異常」,大家不妨將第 10 行代碼改為 char ch1 = str[100000000];,訪問第 100 個字符可能不會發生異常,但是訪問第 1 億個字符肯定會發生異常了,這個異常就是內存訪問錯誤。運行更改后的程序,會發現第 10 行代碼產生了異常,導致程序崩潰了,這說明 try-catch 并沒有捕獲到這個異常。
關于「如何拋出異常」,我們將在下節講解,這里重點是讓大家明白異常的處理流程:
1) 下面的例子演示了 try 塊中直接發生的異常:#include <iostream> #include <string> #include <exception> using namespace std;
int main(){ try{ throw "Unknown Exception"; //拋出異常 cout<<"This statement will not be executed."<<endl; }catch(const char* &e){ cout<<e<<endl; }
return 0; }
運行結果:
Unknown Exception
throw關鍵字用來拋出一個異常,這個異常會被 try 檢測到,進而被 catch 捕獲。關于 throw 的用法,我們將在下節深入講解,這里大家只需要知道,在 try 塊中直接拋出的異常會被 try 檢測到。
2) 下面的例子演示了 try 塊中調用的某個函數中發生了異常:#include <iostream> #include <string> #include <exception> using namespace std;
void func(){ throw "Unknown Exception"; //拋出異常 cout<<"[1]This statement will not be executed."<<endl; }
int main(){ try{ func(); cout<<"[2]This statement will not be executed."<<endl; }catch(const char* &e){ cout<<e<<endl; }
return 0; }
運行結果:
Unknown Exception
func() 在 try 塊中被調用,它拋出的異常會被 try 檢測到,進而被 catch 捕獲。從運行結果可以看出,func() 中的 cout 和 try 中的 cout 都沒有被執行。
3) try 塊中調用了某個函數,該函數又調用了另外的一個函數,這個另外的函數拋出了異常:#include <iostream> #include <string> #include <exception> using namespace std;
void func_inner(){ throw "Unknown Exception"; //拋出異常 cout<<"[1]This statement will not be executed."<<endl; }
void func_outer(){ func_inner(); cout<<"[2]This statement will not be executed."<<endl; }
int main(){ try{ func_outer(); cout<<"[3]This statement will not be executed."<<endl; }catch(const char* &e){ cout<<e<<endl; }
return 0; }
運行結果:
Unknown Exception
發生異常后,程序的執行流會沿著函數的調用鏈往前回退,直到遇見 try 才停止。在這個回退過程中,調用鏈中剩下的代碼(所有函數中未被執行的代碼)都會被跳過,沒有執行的機會了。
1) 語法錯誤在編譯和鏈接階段就能發現,只有 100% 符合語法規則的代碼才能生成可執行程序。語法錯誤是最容易發現、最容易定位、最容易排除的錯誤,程序員最不需要擔心的就是這種錯誤。
2) 邏輯錯誤是說我們編寫的代碼思路有問題,不能夠達到最終的目標,這種錯誤可以通過調試來解決。
3) 運行時錯誤是指程序在運行期間發生的錯誤,例如除數為 0、內存分配失敗、數組越界、文件不存在等。C++ 異常(Exception)機制就是為解決運行時錯誤而引入的。
運行時錯誤如果放任不管,系統就會執行默認的操作,終止程序運行,也就是我們常說的程序崩潰(Crash)。 C++ 提供了異常(Exception)機制,讓我們能夠捕獲運行時錯誤,給程序一次“起死回生”的機會,或者至少告訴用戶發生了什么再終止程序。
【例1】一個發生運行時錯誤的程序:
at() 是 string 類的一個成員函數,它會根據下標來返回字符串的一個字符。與 [ ]不同,at() 會檢查下標是否越界,如果越界就拋出一個異常;而 [ ]不做檢查,不管下標是多少都會照常訪問。 所謂拋出異常,就是報告一個運行時錯誤,程序員可以根據錯誤信息來進一步處理。 上面的代碼中,下標 100 顯然超出了字符串 str 的長度。由于第 6 行代碼不會檢查下標越界,雖然有邏輯錯誤,但是程序能夠正常運行。而第 8 行代碼則不同,at() 函數檢測到下標越界會拋出一個異常,這個異常可以由程序員處理,但是我們在代碼中并沒有處理,所以系統只能執行默認的操作,也即終止程序執行。
捕獲異常
我們可以借助 C++ 異常機制來捕獲上面的異常,避免程序崩潰。捕獲異常的語法為:try{
? ? // 可能拋出異常的語句
}catch(exceptionType variable){
? ? // 處理異常的語句
}
這就好比,catch 告訴 try:你去檢測一下程序有沒有錯誤,有錯誤的話就告訴我,我來處理,沒有的話就不要理我!
catch 關鍵字后面的 exceptionType variable指明了當前 catch 可以處理的異常類型,以及具體的出錯信息。我們稍后再對異常類型展開講解,當務之急是演示一下 try-catch 的用法,先讓讀者有一個整體上的認識。
【例2】修改上面的代碼,加入捕獲異常的語句:
(
[2]out of bound!
可以看出,第一個 try 沒有捕獲到異常,輸出了一個沒有意義的字符(垃圾值)。因為 [ ]不會檢查下標越界,不會拋出異常,所以即使有錯誤,try 也檢測不到。 換句話說,發生異常時必須將異常明確地拋出,try 才能檢測到;如果不拋出來,即使有異常 try 也檢測不到。所謂拋出異常,就是明確地告訴程序發生了什么錯誤。
第二個 try 檢測到了異常,并交給 catch 處理,執行 catch 中的語句。需要說明的是,異常一旦拋出,會立刻被 try 檢測到,并且不會再執行異常點(異常發生位置)后面的語句。本例中拋出異常的位置是第 17 行的 at() 函數,它后面的 cout 語句就不會再被執行,所以看不到它的輸出。
說得直接一點,檢測到異常后程序的執行流會發生跳轉,從異常點跳轉到 catch 所在的位置,位于異常點之后的、并且在當前 try 塊內的語句就都不會再執行了;即使 catch 語句成功地處理了錯誤,程序的執行流也不會再回退到異常點,所以這些語句永遠都沒有執行的機會了。本例中,第 18 行代碼就是被跳過的代碼。
執行完 catch 塊所包含的代碼后,程序會繼續執行 catch 塊后面的代碼,就恢復了正常的執行流。
為了演示「不明確地拋出異常就檢測不到異常」,大家不妨將第 10 行代碼改為 char ch1 = str[100000000];,訪問第 100 個字符可能不會發生異常,但是訪問第 1 億個字符肯定會發生異常了,這個異常就是內存訪問錯誤。運行更改后的程序,會發現第 10 行代碼產生了異常,導致程序崩潰了,這說明 try-catch 并沒有捕獲到這個異常。
關于「如何拋出異常」,我們將在下節講解,這里重點是讓大家明白異常的處理流程:
拋出(Throw)--> 檢測(Try) --> 捕獲(Catch)
發生異常的位置
異常可以發生在當前的 try 塊中,也可以發生在 try 塊所調用的某個函數中,或者是所調用的函數又調用了另外的一個函數,這個另外的函數中發生了異常。這些異常,都可以被 try 檢測到。1) 下面的例子演示了 try 塊中直接發生的異常:
Unknown Exception
throw關鍵字用來拋出一個異常,這個異常會被 try 檢測到,進而被 catch 捕獲。關于 throw 的用法,我們將在下節深入講解,這里大家只需要知道,在 try 塊中直接拋出的異常會被 try 檢測到。
2) 下面的例子演示了 try 塊中調用的某個函數中發生了異常:
Unknown Exception
func() 在 try 塊中被調用,它拋出的異常會被 try 檢測到,進而被 catch 捕獲。從運行結果可以看出,func() 中的 cout 和 try 中的 cout 都沒有被執行。
3) try 塊中調用了某個函數,該函數又調用了另外的一個函數,這個另外的函數拋出了異常:
Unknown Exception
發生異常后,程序的執行流會沿著函數的調用鏈往前回退,直到遇見 try 才停止。在這個回退過程中,調用鏈中剩下的代碼(所有函數中未被執行的代碼)都會被跳過,沒有執行的機會了。
總結
以上是生活随笔為你收集整理的c++ try catch的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: cmake 安装mysql5.6_使用c
- 下一篇: 闪存原理