【C++】异常处理:catch块执行后程序如何继续

文章目录

当异常被捕获后, 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();
}

关键总结

  1. catch块内的代码会执行
  2. catch块之后的代码也会执行(除非catch块中有return/throw/exit等)
  3. 异常抛出点之后的try块代码不会执行
  4. ⚠️ 异常必须在某处被捕获,否则程序终止
相关推荐
徐某人..1 小时前
基于i.MX6ULL平台的智能网关系统开发
arm开发·c++·单片机·qt·物联网·学习·arm
跨境数据猎手1 小时前
跨境独立站系统技术拆解(附带源码)
服务器·前端·php
无敌秋2 小时前
# C++ 简单工厂模式实战指南
c++·简单工厂模式
cany10002 小时前
C++ -- 模板的声明和定义
开发语言·c++
澈2072 小时前
深耕进阶 Day1:C 与 C++ 核心差异 + C++ 入门基石
c语言·开发语言·c++
小龙在慢慢变强..2 小时前
目录结构(FHS 标准)
linux·运维·服务器
脱氧核糖核酸__2 小时前
LeetCode热题100——234.回文链表(两种解法)
c++·算法·leetcode·链表
愚者游世2 小时前
noexcept 说明符与 noexcept运算符各版本异同
开发语言·c++·程序人生·面试·visual studio
Diros1g2 小时前
如何通过普通网线给另一个设备供网
网络·网络协议
beyond阿亮3 小时前
IEC104 Client Simulator - IEC104 主站/客户端模拟器 仿真器免费使用教程
运维·服务器·网络