文章目录
-
- [1. **基本流程示例**](#1. 基本流程示例)
- [2. **不同情况分析**](#2. 不同情况分析)
-
- a) 重新抛出异常(throw;) 重新抛出异常(throw;))
- b) 抛出新异常 抛出新异常)
- c) 函数中的异常处理 函数中的异常处理)
- [3. **多个catch块的情况**](#3. 多个catch块的情况)
- [4. **嵌套异常处理**](#4. 嵌套异常处理)
- [5. **重要的特殊场景**](#5. 重要的特殊场景)
-
- a) catch块中返回 catch块中返回)
- b) 构造函数异常的特殊性 构造函数异常的特殊性)
- c) 析构函数异常(极度危险) 析构函数异常(极度危险))
- [6. **最佳实践建议**](#6. 最佳实践建议)
当异常被捕获后, catch块中的代码会正常执行 ,然后程序会 继续执行catch块之后的代码 (除非catch块中又抛出了新的异常或调用了exit等函数)。
1. 基本流程示例
cpp
#include <iostream>
int main() {
try {
std::cout << "1. try块开始" << std::endl;
throw std::runtime_error("测试异常");
std::cout << "这行不会执行!" << std::endl; // ❌ 被跳过
}
catch (const std::exception& e) {
std::cout << "2. 捕获异常: " << e.what() << std::endl;
// ✅ catch块内的代码会执行
}
std::cout << "3. catch块后的代码继续执行" << std::endl;
return 0;
}
// 输出:
// 1. try块开始
// 2. 捕获异常: 测试异常
// 3. catch块后的代码继续执行
2. 不同情况分析
a) 重新抛出异常(throw;)
cpp
try {
throw std::runtime_error("原始异常");
}
catch (...) {
std::cout << "捕获到异常,但重新抛出" << std::endl;
throw; // 重新抛出,后面的代码不会执行
std::cout << "这行不会执行" << std::endl;
}
// catch块后的代码也不会执行
b) 抛出新异常
cpp
try {
throw 1;
}
catch (int e) {
std::cout << "捕获int异常: " << e << std::endl;
throw "新异常"; // 抛出新的异常
// 后面的代码不会执行
}
catch (const char* e) {
std::cout << "捕获char*异常: " << e << std::endl;
}
std::cout << "这行会执行" << std::endl;
c) 函数中的异常处理
cpp
#include <iostream>
void processData(int value) {
if (value < 0) {
throw std::invalid_argument("数值不能为负");
}
std::cout << "处理数值: " << value << std::endl;
}
int main() {
std::cout << "程序开始" << std::endl;
try {
processData(-5); // 抛出异常
processData(10); // ❌ 这行不会执行
}
catch (const std::exception& e) {
std::cout << "错误: " << e.what() << std::endl;
// ✅ catch块内的代码执行
}
processData(20); // ✅ 这行会执行,因为异常已被处理
std::cout << "程序结束" << std::endl;
return 0;
}
// 输出:
// 程序开始
// 错误: 数值不能为负
// 处理数值: 20
// 程序结束
3. 多个catch块的情况
cpp
try {
throw std::string("字符串异常");
}
catch (int e) {
std::cout << "捕获int: " << e << std::endl;
}
catch (const std::string& e) {
std::cout << "捕获string: " << e << std::endl;
// ✅ 这个catch块会执行
}
catch (...) {
std::cout << "捕获未知异常" << std::endl;
}
std::cout << "继续执行..." << std::endl;
4. 嵌套异常处理
cpp
#include <iostream>
#include <stdexcept>
void innerFunction() {
try {
throw std::runtime_error("内部错误");
}
catch (const std::exception& e) {
std::cout << "内部处理: " << e.what() << std::endl;
// 异常已在内部处理,不会传播到外部
}
std::cout << "内部函数继续执行" << std::endl;
}
void outerFunction() {
try {
innerFunction();
std::cout << "外部函数继续执行" << std::endl; // ✅ 会执行
}
catch (...) {
std::cout << "外部捕获异常" << std::endl; // ❌ 不会执行
}
}
int main() {
outerFunction();
return 0;
}
5. 重要的特殊场景
a) catch块中返回
cpp
bool process() {
try {
throw std::runtime_error("错误");
}
catch (...) {
std::cout << "发生错误" << std::endl;
return false; // 从函数返回
}
std::cout << "这行不会执行" << std::endl; // ❌ 因为已经return了
return true;
}
b) 构造函数异常的特殊性
cpp
class Test {
int* ptr;
public:
Test() : ptr(new int[100]) {
throw std::runtime_error("构造失败");
// 构造函数中的异常:
// 1. 对象不会构造完成
// 2. 成员ptr的内存会泄漏(需要智能指针解决)
}
~Test() { delete[] ptr; } // 不会被调用
};
c) 析构函数异常(极度危险)
cpp
class BadClass {
public:
~BadClass() noexcept(false) {
// 析构函数中抛异常极其危险
throw std::exception(); // ❌ 可能导致程序terminate
}
};
6. 最佳实践建议
cpp
void safeProcessing() {
std::ifstream file("data.txt");
if (!file) {
throw std::runtime_error("无法打开文件");
}
try {
// 复杂的处理逻辑
processFile(file);
}
catch (const std::ios_base::failure& e) {
std::cerr << "IO错误: " << e.what() << std::endl;
// 清理资源
file.close();
throw; // 重新抛出给上层
}
catch (const std::exception& e) {
std::cerr << "处理错误: " << e.what() << std::endl;
// 继续执行其他逻辑或返回错误码
}
// 正常情况继续执行
postProcessing();
}
关键总结:
- ✅ catch块内的代码会执行
- ✅ catch块之后的代码也会执行(除非catch块中有return/throw/exit等)
- ❌ 异常抛出点之后的try块代码不会执行
- ⚠️ 异常必须在某处被捕获,否则程序终止