C++ 例外處理
你好,有抱負的程式設計師們!今天,我們將踏上一段令人興奮的旅程,進入C++例外處理的世界。作為你友善的鄰居電腦科學老師,我將引導你通過這個重要的主題。所以,拿起你喜歡的飲料,放鬆一下,我們一起深入探討吧!
例外是什麼?
在我們像經驗豐富的雜技演員一樣拋出和捕獲例外之前,讓我們先了解例外是什麼。在程式設計的世界中,例外是在程式執行期間發生的意料之外的事件。它們就像我以前經常給的驚喜小測試一樣(對此表示歉意!)——意料之外,有時候要處理起來也相當具有挑戰性。
例外會中斷程式指令的正常流程。它們可能由各種因素引起,例如:
- 除以零
- 超出數組界限訪問
- 過度使用記憶體
- 试图打開不存在的文件
現在,讓我們看看C++如何讓我們從容地面對這些意料之外的情況。
拋出例外
拋出的基本知識
在C++中,我們使用throw
關鍵字來引發一個例外。這就像在課堂上舉手一樣,當你有問題或麻煩時。以下是一個簡單的例子:
#include <iostream>
using namespace std;
int main() {
try {
throw 20;
}
catch (int e) {
cout << "發生了一個例外。例外編號 " << e << endl;
}
return 0;
}
在這個例子中,我們引發了一個整數例外,值為20。但別擔心,我們馬上就會捕獲它!
拋出不同的類型
C++非常靈活,允許你拋出各種類型的例外。讓我們看一下更實際的例子:
#include <iostream>
#include <stdexcept>
using namespace std;
double divide(int a, int b) {
if (b == 0) {
throw runtime_error("除以零!");
}
return static_cast<double>(a) / b;
}
int main() {
try {
cout << divide(10, 2) << endl; // 這將正常工作
cout << divide(10, 0) << endl; // 這將引發一個例外
}
catch (const runtime_error& e) {
cout << "捕獲到例外:" << e.what() << endl;
}
return 0;
}
在這個例子中,當某人試圖除以零時,我們引發了一個runtime_error
例外。這就像在我們的數學社區中貼上一個“禁止除以零”的標誌!
捕獲例外
捕獲的基本知識
現在我們知道了如何拋出例外,讓我們學習如何捕獲它們。捕獲例外就像成為一個負責任的寵物主人——你需要準備好處理你的代碼拋出的任何問題!
我們使用try-catch
塊來捕獲例外。try
塊包含可能拋出例外的代碼,而catch
塊則處理如果發生例外時的情況。
#include <iostream>
using namespace std;
int main() {
try {
int age = -5;
if (age < 0) {
throw "年齡不能為負數!";
}
cout << "年齡是:" << age << endl;
}
catch (const char* msg) {
cerr << "錯誤:" << msg << endl;
}
return 0;
}
在這個例子中,我們檢查年齡是否為負數。如果是,我們引發一個帶有自定義錯誤消息的例外。
捕獲多個例外
有時,同一個代碼片段可能會拋出不同類型的例外。在這種情況下,我們可以有多個catch
塊:
#include <iostream>
#include <stdexcept>
using namespace std;
int main() {
try {
int choice;
cout << "輸入1引發整數例外,輸入2引發運行時錯誤:";
cin >> choice;
if (choice == 1) {
throw 42;
} else if (choice == 2) {
throw runtime_error("出現了一個野生的運行時錯誤!");
} else {
throw "未知選擇!";
}
}
catch (int e) {
cout << "捕獲到整數例外:" << e << endl;
}
catch (const runtime_error& e) {
cout << "捕獲到運行時錯誤:" << e.what() << endl;
}
catch (...) {
cout << "捕獲到一個未知例外!" << endl;
}
return 0;
}
這個例子展示了如何捕獲不同類型的例外。catch (...)
塊是一個捕獲所有其他未捕獲例外的 safety net。它就像對所有那些意料之外的驚喜的一個安全網!
C++標準例外
C++帶有一組你可以 在你的程式中使用的標準例外。這些就像例外世界中的瑞士軍刀——多功能且隨時準備幫助!
以下是一些常見標準例外的表格:
例外 | 描述 |
---|---|
std::runtime_error | 運行時邏輯錯誤 |
std::logic_error | 邏輯錯誤 |
std::out_of_range | 超出訪問範圍 |
std::overflow_error | 算術溢出 |
std::bad_alloc | 記憶體分配失敗 |
讓我們看一下使用標準例外的例子:
#include <iostream>
#include <vector>
#include <stdexcept>
using namespace std;
int main() {
vector<int> numbers = {1, 2, 3, 4, 5};
try {
cout << numbers.at(10) << endl; // 這將引發一個out_of_range例外
}
catch (const out_of_range& e) {
cerr << "超出範圍錯誤:" << e.what() << endl;
}
return 0;
}
在這個例子中,我們試圖訪問向量中超出範圍的元素。當這發生時,at()
函數會引發一個out_of_range
例外。
定義新的例外
雖然標準例外很好,但有時你可能需要更符合你特定需求的東西。這就是自定義例外派上用場的地方!
以下是如何定義你自己的例外類別:
#include <iostream>
#include <exception>
using namespace std;
class NegativeValueException : public exception {
public:
const char* what() const throw() {
return "不允許負值!";
}
};
double squareRoot(double x) {
if (x < 0) {
throw NegativeValueException();
}
return sqrt(x);
}
int main() {
try {
cout << squareRoot(25) << endl; // 這將正常工作
cout << squareRoot(-5) << endl; // 這將引發我們的自定義例外
}
catch (const NegativeValueException& e) {
cerr << "錯誤:" << e.what() << endl;
}
return 0;
}
在這個例子中,我們創建了一個自定義的NegativeValueException
類別。我們在squareRoot
函數中使用它來引發一個例外,當某人試圖計算負數的平方根時。
就是這樣,各位!我們已經涵蓋了C++例外處理的基礎。請記住,例外是你的朋友。它們幫助你编写更健壯、更容錯的代碼。繼續練習,你將會成為捕獲例外的高手!
編程愉快,願你的例外永遠被捕獲!
Credits: Image by storyset