C++ 例外處理

你好,有抱負的程式設計師們!今天,我們將踏上一段令人興奮的旅程,進入C++例外處理的世界。作為你友善的鄰居電腦科學老師,我將引導你通過這個重要的主題。所以,拿起你喜歡的飲料,放鬆一下,我們一起深入探討吧!

C++ Exception Handling

例外是什麼?

在我們像經驗豐富的雜技演員一樣拋出和捕獲例外之前,讓我們先了解例外是什麼。在程式設計的世界中,例外是在程式執行期間發生的意料之外的事件。它們就像我以前經常給的驚喜小測試一樣(對此表示歉意!)——意料之外,有時候要處理起來也相當具有挑戰性。

例外會中斷程式指令的正常流程。它們可能由各種因素引起,例如:

  1. 除以零
  2. 超出數組界限訪問
  3. 過度使用記憶體
  4. 试图打開不存在的文件

現在,讓我們看看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