本篇介紹 c++ exception 例外處理,程式在執行過程中可能會發生一些特殊情況的異常,例如:記憶體不夠、越界存取,所以我們可以用 try catch 來處理這種例外情形
C++ 基本的 try… catch… 例外處理
最簡單的例外處理的寫法如下,使用 try... catch...
所組成,
用 try 包住可能會發生例外的程式碼區段,
用 catch 來處理這個 try 區域所發生的例外,what()
是 exception 類別提供的一個 public method,exception 類別會被所有子類重載,所以不管發生哪種例外,只要呼叫 exception 類的 what()
方法,就會取得該種例外的發生的原因,這個機制是用 C++ virtual 所完成的,程式碼中的 e.what()
將回傳例外產生的原因字串。
另外,catch 裡面的 exception 變數應該要用 reference 的方式。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using namespace std;
int main()
{
try {
// ...
} catch (std::exception &e) { // exception should be caught by reference
cout << "exception: " << e.what() << "\n";
}
return 0;
}
接下來我們來看看實戰中的例外範例,
C++ vector 的 out_of_range 例外處理
C++ vector 存取元素的方式有兩種,一種是使用 []
operator,例如:v[0] = 0
,
另一種是使用 at()
,例如:v.at(0) = 0
,
這兩個的差別在於使用 []
operator 存取超界時不會丟出例外 exception,
所以像下面這個例子中的 v[3]
實際上是讀取了不知名的記憶體位置的數值,
使用 at()
存取超界時會丟出 std::out_of_range
的例外 exception,
所以下面這個範例我們嘗試捕捉看看例外,1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25// g++ cpp-exception.cpp -o a.out -std=c++11
using namespace std;
int main()
{
vector<int> v = {1,2,3};
try {
cout << v[0] << "\n";
cout << v[1] << "\n";
cout << v[2] << "\n";
cout << v[3] << "\n";
cout << v.at(0) << "\n";
cout << v.at(1) << "\n";
cout << v.at(2) << "\n";
cout << v.at(3) << "\n";
} catch (std::exception &e) {
cout << "exception: " << e.what() << "\n";
}
return 0;
}
程式輸出如下,可以發現 使用 v[3]
operator 存取超界用 try... catch...
是捕捉不到例外的,
但是當程式執行到 v.at(3)
時存取超界拋出了例外 exception,
1 | 1 |
常見的 exception 例外
以下幾乎是所以有的 exception 例外種類,C++11 以及之後加入的 exception 未列在下面,
例外種類 | 說明 |
---|---|
std::exception | 所有標準 C++ 例外的父類 |
std::bad_alloc | new 配置記憶體失敗時拋出,可能是記憶體不足 |
std::bad_cast | dynamic_cast 失敗時拋出 |
std::bad_exception | 無法預期的例外 |
std::bad_typeid | typeid 拋出 |
std::logic_error | 程式碼邏輯異常拋出 |
std::runtime_error | 執行期間的例外 |
std::domain_error | Domain error exception |
std::invalid_argument | 無效的參數時拋出 |
std::length_error | 建立長度太長時拋出,例外:std::string |
std::out_of_range | 存取越界時拋出,例如:std::vector |
std::overflow_error | 溢位時拋出 |
std::range_error | Range error exception |
std::underflow_error | 算術下溢時拋出 |
重新拋出例外 exception
在 C++ 中有時候這個例外 exception 捕捉到了,但是某些原因未去處理或還不想處理,想要將該例外重新拋出,就需要使用 throw
這個關鍵字,
重新拋出例外 exception 後,讓該例外交給更外層的例外捕捉處理,1
2
3
4
5
6try {
// ...
} catch (execption &e) {
cout<< e.what() << "\n";
throw; // 重新拋出例外
}
參考
Exceptions - C++ Tutorials
http://www.cplusplus.com/doc/tutorial/exceptions/
exception - C++ Reference
http://www.cplusplus.com/reference/exception/exception/
std::exception - cppreference.com
https://en.cppreference.com/w/cpp/error/exception
簡介例外處理
https://openhome.cc/Gossip/CppGossip/ExceptionHandling.html
C++ 异常处理 | 菜鸟教程
https://www.runoob.com/cplusplus/cpp-exceptions-handling.html
Throwing out of range exception in C++ - Stack Overflow
https://stackoverflow.com/questions/2709719/throwing-out-of-range-exception-in-c/2709733
XYZ的筆記本: C++ 捕捉不到 vector 超出範圍的例外 ?
https://xyz.cinc.biz/2013/10/c-vector-try-catch-out-of-range-exception.html
其它相關文章推薦
C/C++ 新手入門教學懶人包
C++ virtual 的兩種用法
C/C++ 字串反轉 reverse
C/C++ call by value傳值, call by pointer傳址, call by reference傳參考 的差別
C++ 類別樣板 class template
std::sort 用法與範例
std::find 用法與範例
std::queue 用法與範例
std::map 用法與範例