- C++
C++ 异常处理教程
- 2025-5-19 22:01:47 @
🛑 C++ 异常处理教程(零基础版)
从0开始学习 try-catch-throw,通俗易懂 + 示例代码 + 图解风格
🔍 什么是异常处理?
在程序运行过程中,有时会遇到错误或意外情况,比如:
- 文件找不到
- 内存分配失败
- 数组越界访问
- 除以0等非法操作
如果不对这些“异常”进行处理,程序可能会崩溃甚至中止。
C++ 的异常处理机制 就是为了让程序可以优雅地应对这些错误,并尽可能恢复或给出提示,而不是直接崩溃。
⚙️ 异常处理的三要素:try
, catch
, throw
关键字 | 含义 |
---|---|
try |
包含可能抛出异常的代码块 |
throw |
主动抛出一个异常 |
catch |
捕获并处理异常 |
✅ 基本结构:
try {
// 可能抛出异常的代码
throw 异常对象;
} catch (异常类型 e) {
// 处理异常
}
🧠 异常处理的工作流程图解
[ try 中发生异常 ]
│
▼
[ 抛出异常 throw ]
│
▼
[ catch 捕获并处理异常 ]
│
▼
[ 程序继续执行(不是崩溃)]
💡 示例一:基本异常处理
📌 场景:尝试除以0
#include <iostream>
using namespace std;
int main() {
try {
int a = 10, b = 0;
if (b == 0)
throw "除数不能为0"; // 抛出异常
int result = a / b; // 这里不会执行了
cout << "结果是:" << result << endl;
}
catch (const char* msg) { // 捕获字符串类型的异常
cout << "捕获到异常:" << msg << endl;
}
cout << "程序继续运行..." << endl;
return 0;
}
✅ 输出:
捕获到异常:除数不能为0
程序继续运行...
🎯 示例二:捕获多种异常类型
你可以根据抛出的不同类型来分别处理异常。
#include <iostream>
using namespace std;
int main() {
try {
int choice;
cout << "请输入选择(1:整数异常, 2:浮点异常, 3:字符串异常):";
cin >> choice;
if (choice == 1)
throw 100; // 整型异常
else if (choice == 2)
throw 3.14; // 浮点异常
else if (choice == 3)
throw "未知错误"; // 字符串异常
}
catch (int e) {
cout << "捕获到整型异常:" << e << endl;
}
catch (double e) {
cout << "捕获到浮点异常:" << e << endl;
}
catch (const char* e) {
cout << "捕获到字符串异常:" << e << endl;
}
cout << "程序继续执行..." << endl;
return 0;
}
🧩 示例三:自定义异常类(面向对象方式)
我们可以使用类来自定义更复杂的异常。
#include <iostream>
#include <string>
using namespace std;
// 自定义异常类
class MyException {
public:
string message;
MyException(string msg) : message(msg) {}
};
int main() {
try {
bool error = true;
if (error)
throw MyException("这是一个自定义异常!");
}
catch (MyException& e) {
cout << "自定义异常信息:" << e.message << endl;
}
cout << "程序正常结束!" << endl;
return 0;
}
✅ 输出:
自定义异常信息:这是一个自定义异常!
程序正常结束!
🧰 标准库中的常见异常类(需要头文件 <stdexcept>
)
类名 | 描述 |
---|---|
std::exception |
所有标准异常的基类 |
std::runtime_error |
运行时错误,如除以0 |
std::range_error |
结果超出范围 |
std::overflow_error |
上溢出 |
std::underflow_error |
下溢出 |
std::logic_error |
逻辑错误,如无效参数 |
std::invalid_argument |
非法参数错误 |
std::out_of_range |
越界访问 |
✅ 示例四:使用标准库异常
#include <iostream>
#include <stdexcept>
using namespace std;
double divide(int a, int b) {
if (b == 0)
throw runtime_error("除数不能为0");
return static_cast<double>(a) / b;
}
int main() {
try {
double res = divide(10, 0);
}
catch (runtime_error& e) {
cout << "运行时异常:" << e.what() << endl;
}
cout << "程序继续执行..." << endl;
return 0;
}
✅ 输出:
运行时异常:除数不能为0
程序继续执行...
🎨 异常处理流程图(伪代码风格)
开始
│
├─→ try 块开始
│
├─→ 如果没有异常 → 正常执行
│
├─→ 如果有异常 → throw 抛出
│
├─→ catch 块匹配异常类型
│
├─→ 处理异常
│
└─→ 继续执行后续代码
🧪 使用建议 & 最佳实践
建议 | 说明 |
---|---|
🔄 不要滥用异常 | 只用于真正“异常”的情况,不要用作普通控制流 |
📦 捕获异常时尽量具体 | 推荐使用具体的类型(如 int , string , 自定义类),而非 ... |
🧹 清理资源 | 在 catch 中也要注意释放内存、关闭文件等资源 |
🧠 使用基类统一处理 | 如果希望统一处理所有异常,可以用 catch(exception& e) |
📤 使用 .what() 方法输出详细信息 |
对于标准异常非常实用 |
🧠 异常安全保证级别(高级概念)
级别 | 说明 |
---|---|
No-throw guarantee | 函数不会抛出任何异常 |
Strong guarantee | 如果抛出异常,状态回滚到调用前 |
Basic guarantee | 异常抛出后,对象仍处于有效状态 |
No guarantee | 无法保证异常后的状态 |
🙋♂️ 如何继续学习?
如果你希望我继续扩展以下内容,请告诉我:
- 如何用 RAII 实现异常安全?
- 如何捕获所有异常?
- 如何将异常与日志系统结合?
- 如何实现嵌套异常处理结构?
😊
📌 结语:
通过本教程,你已经掌握了 C++ 异常处理的基本语法和使用场景。它是编写健壮程序的重要组成部分,特别是在大型项目中,合理的异常处理可以大大提升程序的稳定性和可维护性!
如果你还有疑问,或者想要配套练习题,也可以随时告诉我 😊
1 条评论
-
admin SU @ 2025-5-19 22:02:44
C++ 异常处理教程(零基础版)
C++ 异常处理是一种处理程序运行时错误的机制,它允许程序在遇到错误时能够优雅地处理问题,而不是直接崩溃。以下是针对零基础学习者的异常处理教程。
1. 什么是异常?
异常是程序在执行期间发生的错误或意外情况,例如:
- 除零错误
- 访问不存在的内存地址
- 文件打开失败
- 数组越界访问
2. 异常处理的基本语法
C++ 异常处理通过三个关键字实现:
try
、catch
和throw
。try { // 可能抛出异常的代码块 if (出现错误条件) { throw 异常值; // 抛出异常 } } catch (异常类型 变量名) { // 处理异常的代码块 // 可以使用变量名访问异常信息 }
3. 抛出异常 (
throw
)使用
throw
语句在程序中抛出异常。异常可以是任何数据类型(通常是类或结构体)。示例:除零错误处理
#include <iostream> using namespace std; double divide(double a, double b) { if (b == 0) { throw "Division by zero!"; // 抛出字符串类型的异常 } return a / b; } int main() { try { double result = divide(10.0, 0.0); cout << "Result: " << result << endl; } catch (const char* error) { cout << "Error: " << error << endl; } return 0; }
输出:
Error: Division by zero!
4. 捕获异常 (
catch
)使用
catch
块捕获并处理异常。catch
块必须紧跟在try
块之后。示例:捕获不同类型的异常
try { int age = -5; if (age < 0) { throw string("Age cannot be negative!"); // 抛出 string 类型异常 } } catch (const char* msg) { cout << "C-style string exception: " << msg << endl; } catch (string& msg) { cout << "String exception: " << msg << endl; // 捕获 string 类型异常 }
5. 多重
catch
块可以使用多个
catch
块捕获不同类型的异常,按顺序匹配。示例:
try { // 可能抛出多种类型异常的代码 } catch (int errorCode) { cout << "Integer error: " << errorCode << endl; } catch (double errorValue) { cout << "Double error: " << errorValue << endl; } catch (...) { // 捕获所有类型的异常(放最后) cout << "Unknown exception occurred." << endl; }
6. 标准异常类
C++ 标准库提供了一组异常类,位于
<exception>
头文件中。常见标准异常类:
std::exception
:所有标准异常的基类std::runtime_error
:运行时错误std::logic_error
:逻辑错误std::out_of_range
:越界访问std::invalid_argument
:无效参数
示例:使用标准异常
#include <stdexcept> // 包含标准异常头文件 int main() { try { vector<int> vec(5); vec.at(10) = 100; // at() 方法会抛出 out_of_range 异常 } catch (const out_of_range& e) { cout << "Exception: " << e.what() << endl; } return 0; }
输出:
Exception: vector::_M_range_check: __n (which is 10) >= this->size() (which is 5)
7. 自定义异常类
可以通过继承
std::exception
类来创建自定义异常。示例:
#include <stdexcept> #include <string> class MyException : public std::exception { private: std::string message; public: MyException(const std::string& msg) : message(msg) {} const char* what() const noexcept override { return message.c_str(); } }; // 使用自定义异常 void checkAge(int age) { if (age < 0) { throw MyException("Invalid age: Age cannot be negative."); } }
8.
try
块嵌套try
块可以嵌套,内层未处理的异常会被外层catch
捕获。示例:
try { try { throw 42; // 抛出整数异常 } catch (double e) { cout << "Inner catch: " << e << endl; } } catch (int e) { cout << "Outer catch: " << e << endl; // 捕获整数异常 }
9. 异常规范(C++11 前)
早期 C++ 允许函数声明异常规范,但 C++11 后已弃用,推荐使用 noexcept。
旧语法(不推荐):
void func() throw(int, char); // 可能抛出 int 或 char 类型异常 void safeFunc() throw(); // 不抛出任何异常
现代语法:
void func() noexcept; // 承诺不抛出异常
10. 最佳实践
- 只捕获能处理的异常:不要盲目捕获所有异常。
- 使用具体的异常类型:避免使用通用的
catch(...)
。 - 异常安全性:确保资源释放(如文件关闭、内存释放)。
- 自定义异常:为特定错误创建有意义的异常类。
- 避免异常泄露:析构函数和
noexcept
函数不应抛出异常。
总结
异常处理是 C++ 中处理错误的强大机制,通过
try
、catch
和throw
可以优雅地处理运行时错误,提高程序的健壮性。建议结合标准异常类和自定义异常类,根据实际需求选择合适的异常处理策略。通过练习上述示例,你可以掌握 C++ 异常处理的基础知识。
- 1