【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. ⚠️ 异常必须在某处被捕获,否则程序终止
相关推荐
代码游侠2 小时前
C语言核心概念复习(一)
c语言·开发语言·c++·笔记·学习
Once_day2 小时前
C++之《Effective C++》读书总结(3)
c语言·c++
腾讯蓝鲸智云2 小时前
【运维自动化-节点管理】节点管理跟配置平台的联动关系
运维·服务器·经验分享·自动化·sass·paas
蜕变的土豆2 小时前
grpc-通关速成
开发语言·c++
FLGB2 小时前
Docker网段和服务器内部网段172.17 网段冲突导致网络不通
服务器·网络·docker
今儿敲了吗2 小时前
10| 扫雷
c++·笔记·学习
代码游侠2 小时前
学习笔记——Linux内核与嵌入式开发3
开发语言·arm开发·c++·学习
星夜落月2 小时前
Web-Check部署全攻略:打造个人网站监控与分析中心
运维·前端·网络
每次学一点3 小时前
【ZeroTier自研之路】planet的组成
服务器·网络·数据库