CH17 例外處理與樣版

Download Report

Transcript CH17 例外處理與樣版

第十七章
例外處理與樣版
課前指引
一個應用程式即使在開發階段編譯都沒有錯誤,但在執行時仍
然可能會發生一些無法預期的錯誤,例如:陣列的註標超出範
圍、除數為 0、開啟的檔案不存在、輸入字元的資料型態不符
( 應輸入數值卻輸入字母) 等等。樣板 (template),就是以相
同的程式碼,提供不同的資料型別,處理功能相似的問題,相
當於其他語言的泛型(Generics)。樣板有函式樣板 (function
template) 和類別樣板(class template) 兩種。
章節大綱
17-1 例外處理
17-2 樣板
備註:可依進度點選小節
17.1 例外處理
一個應用程式即使在開發階段編譯都沒有錯
誤,但在執行時仍然可能會發生一些無法預
期的錯誤
例如:陣列的註標超出範圍、除數為 0、開
啟的檔案不存在、輸入字元的資料型態不符
( 應輸入數值卻輸入字母) 等等。
3
17.1 例外處理
try⋯throw⋯catch 錯誤處理
由於除法運算中,除數為 0 會產生錯誤,在還沒
有學習例外處理之前,如果要撰寫一個 C++ 除法
程式,並由使用者輸入被除數與除數,必須事先
判斷分母是否為 0,以避免除數為 0 的錯誤。
避免除數為 0 的程式
4
17.1 例外處理
try⋯throw⋯catch 錯誤處理
C++ 中的例外處理使用三個關鍵字來進行:
try、throw、catch,其語法架構如下:
5
17.1 例外處理
try⋯throw⋯catch 錯誤處理
例如:判斷 y 是否為 0,若是 y=0 以 throw
1 丟出 int 數值型別1。
6
17.1 例外處理
try⋯throw⋯catch 錯誤處理
上例程式中,當檢查到錯誤發生時 (y==0),使用
throw 丟出一個錯誤型別( 本例為 throw 1 丟出
數值型別 1),這個錯誤型別可以是一個整數、浮
點數、字串或是物件。
錯誤型別丟出之後,會離開 try 區塊,然後開始
比對 catch 中設定的資料型別,如果有找到對應
的型別,就執行該區塊中的程式碼,執行完後就
離開整個 try...catch
「catch(⋯)」可以設定也可省略,若有使用
catch(⋯),則可以補捉 catch() 未定義的其它
型別錯誤。
7
17.1 例外處理
範例時間:產生系統錯誤並且導致程式中斷
詳細步驟,請翻閱課本17-4頁說明。
執行結果
8
17.1 例外處理
範例時間:以 try、throw、catch 處理系統
錯誤
詳細步驟,請翻閱課本17-5頁說明。
執行結果
9
17.1 例外處理
補捉任何型別的錯誤處理
求餘數運算中,數值輸入時,除了檢查數值合理
的範圍外,如果輸入的是其它非數字的字元,最
好也能提示錯誤。
此外,如果分母是負數也要避免,下一個範例中
,我們將呈現這些錯誤的處理。
10
17.1 例外處理
範例時間:補捉任何型別的錯誤處理
詳細步驟,請翻閱課本17-6至17-7頁說明。
執行結果
11
17.1 例外處理
當cin 讀取非字元產生錯誤時,如何清除
std::cin 的內部錯誤訊息和 input buffer
裡剩餘的資料?
上例的輸入過程中,cin 標準輸入會讀入一
個個的字元,並做轉換,一直到無法轉換為
止。
當輸入非數字字元以致無法轉換時,input
stream 會設定內部的錯誤訊息,並停止運作
(輸入),一直到你明確的消除這個錯誤訊息
為止,可以 cin.good()判斷輸入字元是否合
法。
12
17.1 例外處理
所有無法轉換的字元會繼續保留在 input
buffer 裡。
如果您未清除 std::cin 的內部錯誤訊息並
清除 input buffer 裡剩餘的資料將無法再
輸入資料,除非以如下程式清除 std::cin
的內部錯誤訊息並清除 input buffer 裡剩
餘的資料,numeric_limits 的標頭檔是
<limits>,記得要 #include <limits>。
13
17.2 樣板
樣板 (template),就是以相同的程式碼,提
供不同的資料型別,處理功能相似的問題,
相當於其他語言的泛型 (Generics)。
樣板有
函式樣板 (function template)
類別樣板 (class template) 兩種。
14
17.2 樣板
函式樣板(function template)
甚麼是函式樣板? 我們先以例子來說明為什麼需要函
式樣板
要比較兩數大小,並將較大數傳回的函式如下:
上面的例子中,將兩個 int 參數 (2、3) 傳入
Max() 函式,而 Max() 函式則傳回 int 返回值。
15
17.2 樣板
函式樣板(function template)
現在假如有兩個字元要比較大小,例如
Max(‘A’,’B’),並傳回較大的字元,怎麼處
理呢?
答案是為字元比較再寫一個多載函式。
16
17.2 樣板
函式樣板(function template)
上例的程式只是將原來的 int 型別改為 char 型
別,雖然也很容易修改,但感覺總像有點多此一
舉似的。
樣板就是為了解決這樣的問題所定義出來的。
定義函式樣板的語法如下:
17
17.2 樣板
函式樣板(function template)
template <class T> 定義樣板 T,T 是型別參數
,其名稱可以自訂
這裡的class 並不是類別,而是定義樣板的語法
。
例如:以 template <class T> 定義函式樣板 T
,其參數型別為 T,傳回值的型別也是T 型別。
18
17.2 樣板
函式樣板(function template)
上例定義了函式樣板後,就可以用下列的語法來
呼叫函式:
函式<資料型別>(參數一,參數二);
例如:設定上例中參數型別 T 的資料型別為 int
又如:設定 T 的資料型別為 char。
事實上,編譯器會自動依照參數的型別來取代,
因此上例也可以省略 T 簡化
如下:
19
17.2 樣板
函式樣板(function template)
我們可以將上面的範例用函式樣板來改進,以
template <class T> 定義函式樣板 T,其參數型
別暫訂為 T,傳回值的型別也是 T 型別,這樣是
不是精簡多了!
20
17.2 樣板
範例時間:比較大小並傳回較大值
詳細步驟,請翻閱課本17-12至17-13頁說明
執行結果
21
17.2 樣板
Max(“Apple”,”Orange”) 的困惑
筆者在實作字串比較
Max(“Apple”,”Orange”),發現 “Apple”、
”Orange”型別並不如預期會以 string 型別取
代函式樣板 T,因為它實際上是 char[] 字元陣
列(字串) 而不是 string 字串。
字元陣列的比較是「strcmp()」¸不是「>」運算
子,因此會得到不正確的結果,這時加上
<string>參數型別就會比較明確。
22
17.2 樣板
Max(“Apple”,”Orange”) 的困惑
但是上列的語法百看不順,因此改為先將參數 s1
、s2 明確宣告為 string,再將 s1 s2當作
Max(s1,s2) 的參數,如下:
23
17.2 樣板
函式樣板(function template)
上面的範例是使用一個型別參數的樣板,也可以
使用多個型別參數的樣板。
還是用例子說明好了,下例為包含有兩個型別參
數樣板 T1、T2 的函式樣板,沒有傳回值,其中
的 show() 函式可以顯示兩種不同的資料型別。
24
17.2 樣板
範例時間:多個型別參數的函式樣板
詳細步驟,請翻閱課本17-14頁說明。
執行結果
25
17.2 樣板
類別樣板
類別也可以宣告為樣板 (template),也就是說可
以將類別的資料成員定義為樣板,讓類別擁有處
理不同資料型別的能力。
定義類別樣板的語法如下:
26
17.2 樣板
類別樣板
以 template <class T> 定義類別樣板 T,T 是
自訂的型別參數。class 不是類別,而是定義類
別樣板的語法。
例如:定義類別樣板 T,並定義 Quene 類別中的
成員 QueneData[5] 的資料型別為 T。
27
17.2 樣板
類別樣板
定義了類別樣板後,就可以以下列的語法來建立
物件。
例如:
以 Quene 類別建立物件 Myint,並設 Quene 類別中類
別樣板 T 的型別為 int 型別。
當成員函式定義在類別外部時,除了在範圍解析
運算子「::」前加上所屬類別外,還要在類別名
稱後面加上 < 類別樣板>,並且必須以 template
<class T> 加上類別樣板的宣告。
28
17.2 樣板
類別樣板
在類別外部定義函式的格式如下:
例如:在類別外部定義 show() 函式。
29
17.2 樣板
類別樣板
上例是以 template <class T> 定義類別樣板 T
,再以樣板 T 宣告類別資料成員QueneData[5],
然後在主程式中以 Quene <int> Myint 建立
Myint 物件,並將類別樣板 T 設為 int,因此實
際執行時,類別的定義如下:
30
17.2 樣板
類別樣板
在資料結構中,佇列可用來儲存資料,直至存滿
為止。
如果我們要將多個int 數值資料,儲存在可以儲
存 5 筆資料的佇列中,則可以撰寫如下的 Quene
類別來處理。
31
17.2 樣板
上例是一個 Quene 佇列類別,內含 QueneData[5] 共 5
個陣列元素可以儲存int 整數型別的資料,Add() 用以將
資料存入佇列中,Index 則是佇列的指標,用以指示佇
列是否已存滿。
32
17.2 樣板
範例:定義類別樣板
詳細步驟,請翻閱課本17-18至17-20頁說明
執行結果
33
17.2 樣板
範例:多個型別參數的類別樣板
詳細步驟,請翻閱課本17-20至17-21頁說明
執行結果
34
本章結束
Q&A討論時間
35