第 18 章 名稱空間與例外處理 18-1 名稱空間 18-1 名稱空間 18-2 例外處理 18-2...

25
18 18 第第第第第第第第第 第第第第第第第第第 18-1 18-1 第第第第 第第第第 18-2 18-2 第第第第 第第第第

Post on 19-Dec-2015

243 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: 第 18 章 名稱空間與例外處理 18-1 名稱空間 18-1 名稱空間 18-2 例外處理 18-2 例外處理

第第 1818 章 章 名稱空間與例外處理名稱空間與例外處理 18-1 18-1 名稱空間名稱空間 18-2 18-2 例外處理例外處理

Page 2: 第 18 章 名稱空間與例外處理 18-1 名稱空間 18-1 名稱空間 18-2 例外處理 18-2 例外處理

18-1 18-1 名稱空間名稱空間 18-1-1 18-1-1 什麼是名稱空間什麼是名稱空間 18-1-2 18-1-2 建立名稱空間建立名稱空間 18-1-3 18-1-3 使用名稱空間使用名稱空間 18-1-4 18-1-4 名稱空間的別名名稱空間的別名 18-1-5 18-1-5 巢狀名稱空間巢狀名稱空間

Page 3: 第 18 章 名稱空間與例外處理 18-1 名稱空間 18-1 名稱空間 18-2 例外處理 18-2 例外處理

18-1-1 18-1-1 什麼是名稱空間什麼是名稱空間 -- 觀念觀念 名稱空間的觀念其實很簡單,其原意是替本文內名稱空間的觀念其實很簡單,其原意是替本文內

容指定一個有意義的識別符號,例如:作者陳會容指定一個有意義的識別符號,例如:作者陳會安是安是 XX 公司的員工,員工編號公司的員工,員工編號 IDID是是 12341234 ,江,江小魚是小魚是 YY 公司的員工,員工編號公司的員工,員工編號 IDID 也是也是 12341234 ,,我們可以使用相同的員工編號我們可以使用相同的員工編號 IDID 來識別陳會安和來識別陳會安和江小魚,因為他們屬於不同的公司,江小魚,因為他們屬於不同的公司, XX 和和 YY 公司公司就是名稱空間的識別符號。就是名稱空間的識別符號。

現在回到計算機科學的程式語言,對於一些簡單現在回到計算機科學的程式語言,對於一些簡單的程式語言來說,只擁有一個名稱空間,所以程的程式語言來說,只擁有一個名稱空間,所以程式中的所有函數和變數名稱都不能同名。有一些式中的所有函數和變數名稱都不能同名。有一些程式語言預設擁有多個固定的名稱空間,所以函程式語言預設擁有多個固定的名稱空間,所以函數和變數允許同名,因為它們分別屬於不同的名數和變數允許同名,因為它們分別屬於不同的名稱空間。稱空間。

Page 4: 第 18 章 名稱空間與例外處理 18-1 名稱空間 18-1 名稱空間 18-2 例外處理 18-2 例外處理

18-1-1 18-1-1 什麼是名稱空間什麼是名稱空間 -C++-C++ 標準標準函式庫的名稱空間函式庫的名稱空間 stdstd

在在 ANSI-C++ANSI-C++ 的標準的標準 C++C++ 函式庫是使用函式庫是使用名稱空間來控制程式範圍,名稱空間來控制程式範圍, ANSI-C++ANSI-C++ 標標準函式庫定義的所有類別、物件和函數,準函式庫定義的所有類別、物件和函數,都屬於名為都屬於名為 stdstd 的標準名稱空間,例如:的標準名稱空間,例如:coutcout、、 cincin和和 stringstring 等類別。等類別。

Page 5: 第 18 章 名稱空間與例外處理 18-1 名稱空間 18-1 名稱空間 18-2 例外處理 18-2 例外處理

18-1-2 18-1-2 建立名稱空間建立名稱空間 -- 說明說明 名稱空間(名稱空間( NamespacesNamespaces )可以結合變數、)可以結合變數、

函數和類別來成為群組,其宣告語法如下函數和類別來成為群組,其宣告語法如下所示:所示:

namespace namespace 名稱空間的識別字 名稱空間的識別字 {{…………}} 上述名稱空間是使用上述名稱空間是使用 namespacenamespace 關鍵字關鍵字

開始,之後是名稱空間的識別字,大括號開始,之後是名稱空間的識別字,大括號括起的是屬於此名稱空間的變數、函數和括起的是屬於此名稱空間的變數、函數和類別。類別。

Page 6: 第 18 章 名稱空間與例外處理 18-1 名稱空間 18-1 名稱空間 18-2 例外處理 18-2 例外處理

18-1-2 18-1-2 建立名稱空間建立名稱空間 -- 建立名稱空建立名稱空間間

在在 C++C++ 語言的名稱空間是定義在一個程式區塊語言的名稱空間是定義在一個程式區塊之中,例如:建立名為之中,例如:建立名為 firstfirst 的名稱空間,如下所的名稱空間,如下所示:示:

namespace first {namespace first { int a, b;int a, b; int sum(int a, int b) { return a+b; }int sum(int a, int b) { return a+b; } class Result {class Result { int sum;int sum; public:public: Result(int s) { sum = s; }Result(int s) { sum = s; } int value() { return sum; }int value() { return sum; } };};}}

Page 7: 第 18 章 名稱空間與例外處理 18-1 名稱空間 18-1 名稱空間 18-2 例外處理 18-2 例外處理

18-1-2 18-1-2 建立名稱空間建立名稱空間 -- 存取名稱空存取名稱空間間

當我們在名稱空間宣告的程式區塊外,存當我們在名稱空間宣告的程式區塊外,存取變數取變數 aa 、、 bb 、類別、類別 ResultResult 和函數和函數sum()sum() 時,程式需要使用名稱空間字首和時,程式需要使用名稱空間字首和「「 :::: 」範圍運算子來存取,如下所示:」範圍運算子來存取,如下所示:

first::Result fr(22);first::Result fr(22);

first::a = 12;first::a = 12;

first::b = 15;first::b = 15;

total1 = first::sum(first::a, first::b);total1 = first::sum(first::a, first::b);

Page 8: 第 18 章 名稱空間與例外處理 18-1 名稱空間 18-1 名稱空間 18-2 例外處理 18-2 例外處理

18-1-3 18-1-3 使用名稱空間使用名稱空間 -- 說明說明 名稱空間包含變數、函數和類別,當在名名稱空間包含變數、函數和類別,當在名

稱空間程式區塊外存取時,我們可以使用稱空間程式區塊外存取時,我們可以使用二種方式來存取名稱空間,如下所示:二種方式來存取名稱空間,如下所示:• 名稱空間字首的明確存取:使用名稱空間名稱名稱空間字首的明確存取:使用名稱空間名稱

的字首和「的字首和「 :::: 」範圍運算子來存取,在第」範圍運算子來存取,在第 18-18-1-21-2 節的程式範例是使用此方式。節的程式範例是使用此方式。

• 使用使用 usingusing 指引指令來存取:使用指引指令來存取:使用 usingusing 指引指引指令來存取名稱空間,在本節的程式範例就是指令來存取名稱空間,在本節的程式範例就是使用此方式來存取名稱空間。使用此方式來存取名稱空間。

Page 9: 第 18 章 名稱空間與例外處理 18-1 名稱空間 18-1 名稱空間 18-2 例外處理 18-2 例外處理

18-1-3 18-1-3 使用名稱空間使用名稱空間 -using -using namespacenamespace 指引指令指引指令

using namespaceusing namespace 指引指令可以簡化指引指令可以簡化 C++C++ 程程式碼來存取名稱空間,其基本語法如下所示:式碼來存取名稱空間,其基本語法如下所示:

using namespace using namespace 名稱空間的識別字名稱空間的識別字 ;; 程式區塊可以直接存取的名稱空間,例如:在程程式區塊可以直接存取的名稱空間,例如:在程

式區塊的開頭使用式區塊的開頭使用 usingusing 宣告使用宣告使用 secondsecond 名稱名稱空間,如下所示:空間,如下所示:

using namespace second;using namespace second; 程式碼宣告在目前的程式區塊,可以直接存取程式碼宣告在目前的程式區塊,可以直接存取

secondsecond 名稱空間,所以存取變數名稱空間,所以存取變數 aa 和和 bb 時,就時,就不需要使用字首不需要使用字首 second::second:: ,如下所示:,如下所示:

a = 12.34;a = 12.34;b = 34.56;b = 34.56;

Page 10: 第 18 章 名稱空間與例外處理 18-1 名稱空間 18-1 名稱空間 18-2 例外處理 18-2 例外處理

18-1-3 18-1-3 使用名稱空間使用名稱空間 -using-using 宣宣告告

在在 C++C++ 程式使用程式使用 using namespaceusing namespace 指引指令,指引指令,表示程式碼可以直接存取整個名稱空間的內容。表示程式碼可以直接存取整個名稱空間的內容。

如果名稱空間包含的變數、函數和類別很多,我如果名稱空間包含的變數、函數和類別很多,我們只打算直接存取其部分成員,此時們只打算直接存取其部分成員,此時 usingusing 宣告宣告就可以指定存取的部分成員,如下所示:就可以指定存取的部分成員,如下所示:

using second::a;using second::a; 上述程式碼宣告只直接存取上述程式碼宣告只直接存取 secondsecond 名稱空間的名稱空間的

變數變數 aa ,所以可以直接存取,所以可以直接存取 aa 變數,如下所示:變數,如下所示:a = 100;a = 100;

Page 11: 第 18 章 名稱空間與例外處理 18-1 名稱空間 18-1 名稱空間 18-2 例外處理 18-2 例外處理

18-1-4 18-1-4 名稱空間的別名名稱空間的別名 對於對於 C++C++ 語言已經存在的名稱空間,我們語言已經存在的名稱空間,我們

可以定義其別名,其基本語法如下所示:可以定義其別名,其基本語法如下所示:namespace namespace 新名稱 新名稱 = = 原名稱空間的識別原名稱空間的識別字字 ;;

上述語法可以指定目前存在名稱空間的新上述語法可以指定目前存在名稱空間的新名稱,例如:替名稱空間名稱,例如:替名稱空間 firstfirst 指定一個新指定一個新名稱名稱 secondsecond ,如下所示:,如下所示:

namespace second = first;namespace second = first; 上述程式碼宣告名稱空間上述程式碼宣告名稱空間 firstfirst 的新名稱的新名稱

secondsecond 。。

Page 12: 第 18 章 名稱空間與例外處理 18-1 名稱空間 18-1 名稱空間 18-2 例外處理 18-2 例外處理

18-1-5 18-1-5 巢狀名稱空間巢狀名稱空間 在在 C++C++ 的名稱空間可以擁有其他名稱空間,例的名稱空間可以擁有其他名稱空間,例

如:如: firstfirst 名稱空間之中擁有名稱空間之中擁有 secondsecond 名稱空間,名稱空間,如下所示:如下所示:

namespace first {namespace first { int a, b;int a, b; namespace second {namespace second { int a , b;int a , b; }}}} 存取內層名稱空間的變數存取內層名稱空間的變數 aa 和和 bb ,如下所示:,如下所示:first::second::a = 56;first::second::a = 56;first::second::b = 78;first::second::b = 78;

Page 13: 第 18 章 名稱空間與例外處理 18-1 名稱空間 18-1 名稱空間 18-2 例外處理 18-2 例外處理

18-2 18-2 例外處理例外處理 18-2-1 18-2-1 例外處理的基礎例外處理的基礎 18-2-2 18-2-2 例外處理的程式敘述例外處理的程式敘述 18-2-3 18-2-3 同時處理多種例外同時處理多種例外 18-2-4 18-2-4 自訂類別型態的例外自訂類別型態的例外

Page 14: 第 18 章 名稱空間與例外處理 18-1 名稱空間 18-1 名稱空間 18-2 例外處理 18-2 例外處理

18-2-1 18-2-1 例外處理的基礎例外處理的基礎 -- 說明說明 C++C++ 語言的「例外」(語言的「例外」( ExceptionException )是)是

指在程式執行時,發生不正常執行的狀態。指在程式執行時,發生不正常執行的狀態。「例外處理」(「例外處理」( Handling ExceptionsHandling Exceptions ))就是用來處理程式產生的例外。就是用來處理程式產生的例外。

例外處理的目的是為了讓程式能夠更加例外處理的目的是為了讓程式能夠更加「強壯」(「強壯」( RobustRobust ),就算程式遇到不),就算程式遇到不尋常情況,也不會造成程式「崩潰」尋常情況,也不會造成程式「崩潰」(( CrashingCrashing ),甚至導致整個系統當機。),甚至導致整個系統當機。

Page 15: 第 18 章 名稱空間與例外處理 18-1 名稱空間 18-1 名稱空間 18-2 例外處理 18-2 例外處理

18-2-1 18-2-1 例外處理的基礎例外處理的基礎 -- 例外處理例外處理的架構的架構

C++C++ 語言的例外處理架構是一種你丟我撿的架構,語言的例外處理架構是一種你丟我撿的架構,當當 C++C++ 程式有不尋常情況產生例外時,程式就程式有不尋常情況產生例外時,程式就開始尋找是否有例外處理可以進行處理,如下圖開始尋找是否有例外處理可以進行處理,如下圖所示:所示:

Page 16: 第 18 章 名稱空間與例外處理 18-1 名稱空間 18-1 名稱空間 18-2 例外處理 18-2 例外處理

18-2-1 18-2-1 例外處理的基礎例外處理的基礎 -- 例外處理例外處理的架構說明的架構說明

在執行過程可能產生兩種型態的例外,如下:在執行過程可能產生兩種型態的例外,如下:• 函數函數 c()c() 丟出字元陣列型態的例外:程式執行丟出字元陣列型態的例外:程式執行

過程倒過來找尋是否有指定型態的例外處理,過程倒過來找尋是否有指定型態的例外處理,首先是函數首先是函數 c()c()和和 b()b() ,因為沒有對應的例外,因為沒有對應的例外處理,所以最後傳遞給函數處理,所以最後傳遞給函數 a()a() ,在此函數擁,在此函數擁有可以處理字元陣列型態的例外處理,可以處有可以處理字元陣列型態的例外處理,可以處理此例外。理此例外。

• 函數函數 b()b() 丟出整數型態的例外:同樣需要找尋丟出整數型態的例外:同樣需要找尋是否有例外處理可以進行處理,以此例雖然函是否有例外處理可以進行處理,以此例雖然函數數 b()b() 擁有例外處理,但是因為例外型態不同,擁有例外處理,但是因為例外型態不同,所以,直到所以,直到 main()main() 主程式才找到正確的例外主程式才找到正確的例外處理。處理。

Page 17: 第 18 章 名稱空間與例外處理 18-1 名稱空間 18-1 名稱空間 18-2 例外處理 18-2 例外處理

18-2-1 18-2-1 例外處理的基礎例外處理的基礎 -C++-C++ 的標的標準例外類別準例外類別

在在 C++C++ 標準函式庫的函數有可能丟出標準例外標準函式庫的函數有可能丟出標準例外類別(類別( Standard Exception ClassesStandard Exception Classes )型態的)型態的例外,這些例外型態都屬於例外,這些例外型態都屬於 exceptionexception 類別的子類別的子類別。類別。 exceptionexception 類別架構如下圖所示:類別架構如下圖所示:

Page 18: 第 18 章 名稱空間與例外處理 18-1 名稱空間 18-1 名稱空間 18-2 例外處理 18-2 例外處理

18-2-1 18-2-1 例外處理的基礎例外處理的基礎 -C++-C++ 的標的標準例外類別說明準例外類別說明

C++C++ 語言標準例外類別的說明,如下表所示:語言標準例外類別的說明,如下表所示:例外類別 說明bad_alloc new運算子失敗的例外bad_cast 在執行期型態轉換dynamic_cast運算子失敗的例外

bad_typeid 在執行期型態識別typeid運算子失敗的例外,其參數值為0

或NULL指標bad_exception 處理沒有預期的例外domain_error 值域錯誤的例外

invalid_argument 不合法參數的例外length_error 超過最大長度的例外,例如:在字串新增太多字元out_of_range 參數不在預期範圍的例外,例如:錯誤的索引值range_error 內部計算的範圍錯誤例外

overflow_error 數學運算溢位(arithmetic overflow)錯誤的例外underflow_error 數學運算不足位(arithmetic underflow)錯誤的例外

Page 19: 第 18 章 名稱空間與例外處理 18-1 名稱空間 18-1 名稱空間 18-2 例外處理 18-2 例外處理

18-2-2 18-2-2 例外處理的程式敘述例外處理的程式敘述 -- 架構架構 例外處理程式敘述分為例外處理程式敘述分為 trytry和和 catchcatch 二個程式區二個程式區

塊,可以建立塊,可以建立 C++C++ 程式的例外處理,其基本語程式的例外處理,其基本語法如下所示:法如下所示:

try { try { ………………}}catch ( ExceptionType parameterName ) {catch ( ExceptionType parameterName ) { ……… ……… // // 例外處理例外處理 ………………}}

Page 20: 第 18 章 名稱空間與例外處理 18-1 名稱空間 18-1 名稱空間 18-2 例外處理 18-2 例外處理

18-2-2 18-2-2 例外處理的程式敘述例外處理的程式敘述 -- 架構架構說明說明

trytry 程式區塊:在程式區塊:在 trytry 程式區塊的程式碼是程式區塊的程式碼是用來檢查是否丟出例外,當例外產生時,用來檢查是否丟出例外,當例外產生時,就會丟出指定型態的例外。就會丟出指定型態的例外。

catchcatch 程式區塊:當程式區塊:當 trytry 程式區塊的程式碼程式區塊的程式碼丟出例外,程式需要準備一到多個丟出例外,程式需要準備一到多個 catchcatch程式區塊來處理不同程式區塊來處理不同 ExceptionTypeExceptionType 資料資料型態參數型態參數 parameterNameparameterName 的例外。的例外。

Page 21: 第 18 章 名稱空間與例外處理 18-1 名稱空間 18-1 名稱空間 18-2 例外處理 18-2 例外處理

18-2-2 18-2-2 例外處理的程式敘述例外處理的程式敘述 -- 範例範例 例如:處理例如:處理 intint資料型態的例外處理程式敘述,資料型態的例外處理程式敘述,

如下所示:如下所示:try {try { // // 檢查是否產生例外的程式碼 檢查是否產生例外的程式碼 }}catch ( int e ) {catch ( int e ) { cout << "cout << " 主程式處理例外主程式處理例外 : " << e << endl;: " << e << endl;}} 上述程式碼的上述程式碼的 catchcatch 程式區塊傳入的是程式區塊傳入的是 intint 整數整數資料型態,可以處理資料型態,可以處理 intint資料型態的例外。資料型態的例外。

Page 22: 第 18 章 名稱空間與例外處理 18-1 名稱空間 18-1 名稱空間 18-2 例外處理 18-2 例外處理

18-2-2 18-2-2 例外處理的程式敘述例外處理的程式敘述 -- 使用使用throwthrow 關鍵字丟出例外關鍵字丟出例外

在在 C++C++ 程式可以使用程式可以使用 throwthrow 關鍵字丟出例外,關鍵字丟出例外,其基本語法如下所示:其基本語法如下所示:

throw exception;throw exception; throwthrow 關鍵字必須在關鍵字必須在 trytry 程式區塊中執行,或是程式區塊中執行,或是從從 trytry 程式區塊所呼叫的函數中執行。程式區塊所呼叫的函數中執行。 throwthrow 關關鍵字類似鍵字類似 returnreturn ,可以丟出指定資料型態的例外。,可以丟出指定資料型態的例外。例如:丟出例如:丟出 intint 整數資料型態的例外,如下所示:整數資料型態的例外,如下所示:

throw value;throw value; valuevalue 變數是變數是 intint 整數資料型態,表示丟出整數資料型態,表示丟出 intint資資料型態的例外,換句話說,料型態的例外,換句話說, C++C++ 程式需要使用程式需要使用相同資料型態的相同資料型態的 catchcatch 程式區塊來進行例外處理。程式區塊來進行例外處理。

Page 23: 第 18 章 名稱空間與例外處理 18-1 名稱空間 18-1 名稱空間 18-2 例外處理 18-2 例外處理

18-2-3 18-2-3 同時處理多種例外同時處理多種例外 在在 C++C++ 程式的程式的 trytry和和 catchcatch 程式敘述,可以使用多個程式敘述,可以使用多個

catchcatch 程式區塊來同時處理多種不同型態的例外,如下所程式區塊來同時處理多種不同型態的例外,如下所示:示:

try {try { ……… ………}}catch ( const exception& e ) {catch ( const exception& e ) { cout << "cout << " 產生例外產生例外 : " << e.what() << endl;: " << e.what() << endl;}}catch ( int i ) {catch ( int i ) { cout << "cout << " 產生例外產生例外 : " << i << endl;: " << i << endl;}}catch ( ... ) {catch ( ... ) { cout << "cout << " 產生未知的例外產生未知的例外 ....." << endl;....." << endl;} }

Page 24: 第 18 章 名稱空間與例外處理 18-1 名稱空間 18-1 名稱空間 18-2 例外處理 18-2 例外處理

18-2-4 18-2-4 自訂類別型態的例外自訂類別型態的例外 -- 建立建立 myExceptionmyException 類別宣告如下所示:類別宣告如下所示:class myException {class myException {private:private: char error_msg[80];char error_msg[80]; int error;int error;public:public: myException() { *error_msg = 0; error = 0; }myException() { *error_msg = 0; error = 0; } myException(char *s, int e) {myException(char *s, int e) { strcpy(error_msg, s);strcpy(error_msg, s); error = e;error = e; }} const char* str_what() { return error_msg; }const char* str_what() { return error_msg; } const int what() { return error; }const int what() { return error; }};};

Page 25: 第 18 章 名稱空間與例外處理 18-1 名稱空間 18-1 名稱空間 18-2 例外處理 18-2 例外處理

18-2-4 18-2-4 自訂類別型態的例外自訂類別型態的例外 -- 丟出丟出 在使用在使用 throwthrow 關鍵字丟出例外時,就是建關鍵字丟出例外時,就是建立立myExceptionmyException 物件,如下所示:物件,如下所示:

throw myException("throw myException(" 不是正整數不是正整數 ", ", value);value);

上述程式碼建立上述程式碼建立 myExceptionmyException 物件,參物件,參數是前述類別宣告的建構子參數。數是前述類別宣告的建構子參數。