105年檢察事務官三等程式語言
四、試說明 C++ 程式語言中的異常處理 (Exception Handling) 之形式,也就是它的構造 (construct)。在一些沒有異常處理設計之語言中,可以做異常處理嗎?亦說明之。(15分) |
答:
(一)C++程式語言異常處理的形式
1.格式:
在 C++ 語言中,引發例外的敘述必須包含在一個 try 結構中,而例外處理程式則定義在 try 結構後面的 catch 子句中,如下格式:
try{
--預期要引發例外的程式碼--
throw Type
}
catch(Type 1) { // catch(形式參數)
--處理程式主體--
}
catch(Type 2) { // catch(形式參數)
--處理程式主體--
}
...
2.參數:
catch子句只能包含單一個形式參數,而形式參數必須具有唯一的型態。參數名稱可以省略,表示執行此例外處理程式時不用傳遞參數。若以省略符號 (...) 為形式參數,表示這是一個可抓住任何例外的處理程式。如下:
catch(...) {
// 處理所有的例外
}
3.無法處理的例外:
C++ 的例外處理程式無法處理硬體或作業系統軟體所引發的例外,只能處理throw 敘述所產生的例外。
4.再度將例外丟出:
如果打算在 catch 中處理完例外之後,再度將例外丟出,則再使用 throw 即可,例如:
catch(...) {
// 處理例外
throw; // 再度丟出
}
如果丟出例外,而 catch 中並沒有相對捕捉該例外的區塊,則程式會呼叫標準函式庫中的 terminate( ) 函式,而預設 terminate( ) 會呼叫 abort( ) 函式來終止程式。
5.宣告函數中可引發的例外型態:
(1)一個C++函數可在函數的標頭列加入throw子句,以宣告此函數中所能引發的例外型態
int fun( ) throw(int, char *) {
...
}
表示在函數 fun 中只能引發 int 及 char * 兩種型態的例外。
(2)若throw之後沒有列出任何型態,表示該函數不能引發例外
(3)若省略throw的宣告,表示該函數可以引發任何例外
6.範例:
#include <iostream> using namespace std; int main(void) { int a = 0; int b = 0; cout << "請輸入被除數: "; cin >> a; cout << "請輸入除數: "; cin >> b; try { if(b == 0) throw "發生除零的錯誤"; cout << "a / b = " << static_cast<double> (a) / b << endl; } catch(int err) { cout << "除數為: " << err << endl; cout << "結果無限大" << endl; } catch(const char* str) { cerr << "錯誤: " << str << endl; } return 0; } |
執行結果:
請輸入被除數: 10
請輸入除數: 0
錯誤: 發生除零的錯誤
--------------------------------
請輸入被除數: 5
請輸入除數: 2
a / b = 2.5
(二)沒有異常處理設計的語言中,可以做異常處理嗎?
在沒有異常處理的語言中,是使用 if-else 或 switch 等敘述,來捕捉 (catch) 程式裡所有可能發生的錯誤。但是如果程式中的異常是硬體所引起 (如硬體錯誤或記憶體不足),則無法進行異常處理 (無法透過程式碼檢測)。例如:
#include <stdio.h> void main( ) { int data; FILE* f = fopen("sample.txt", "r"); // sample.txt may not exist, fopen returns NULL fscanf(f, "%d", &data); // may result segmentation fault; } |
如果檔案 sample.txt 不存在,則無法開啟該檔案,比較好的寫法是:
#include <stdio.h> void main( ) { int data; FILE* f = fopen("sample.txt", "r"); // sample.txt may not exist, fopen returns NULL if (f == NULL) { printf("Can't open file sample.txt. \n"); return; } fscanf(f, "%d", &data); // may result segmentation fault; } |
fopen 傳回 NULL。如果不檢查傳回值,則會產生 segmentation fault。
※參考資料:http://programming.im.ncnu.edu.tw/J_Chapter8.htm
留言列表