news 2026/2/15 22:25:21

【C++】2.9异常处理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【C++】2.9异常处理

目录

1. 抛出异常

2. 栈展开

3. 查找匹配代码

应用示例

模拟发送函数

4. 安全问题

5. 异常规范


1. 抛出异常

  • 异常抛出后,沿着调用链,在里层或外层都能被处理。

  • 捕获 (catch) 规则:由作用链上类型匹配最近的捕获。

int func() { int a; int b; cin >> a >> b; try { if (b == 0) { string s("divide by 0"); throw s; } else { return a / b; } } catch (int s) { cout << s << endl; } } int main() { try { cout << func(); } catch (const string& s) { cout << s << endl; } catch (...) { cout << "unknown" << endl; } return 0; }
  • 在函数中,若输入 1, 0,由于函数内最近的catch要求int类型,不匹配,因此继续向下抛出,到main函数中匹配string类型的捕获。

  • catch (...)可以捕获任何类型的异常,作为程序的兜底,防止因为异常找不到匹配的catch而崩溃。

2. 栈展开

  • 抛出异常后,由于后面的程序不执行,函数栈帧会不断销毁,直到找到最近的可接受该异常的处理代码。

  • 若直到main函数都没找到可以catch的,程序就会直接报错。

3. 查找匹配代码

  • 规则:多个catch匹配就选更近的;允许常量转为非常量;允许数组转为指针;允许子类转为父类。

  • 在大型项目中,一般会选用子类转为父类的规则。

应用示例

class basemod { public: basemod(const string& errmsg, int id) :_errmsg(errmsg) , _id(id) { } virtual string what() const { return _errmsg; } int getid() const { return _id; } protected: string _errmsg; int _id; }; class Amod :public basemod { public: Amod(const string& errmsg, int id, const string& data) :basemod(errmsg, id) , _data(data) { } virtual string what() const { string str = "Amod"; str += _errmsg; str += "->"; str += _data; return str; } protected: string _data; };
  • 假设在这个项目中有 A 模块(发送模块)继承了基类。what函数用于生成报错信息,id用于存储报错值。

catch (const basemod& b) { cout << b.what() << endl; }
  • 由于what是虚函数,因此不同的子类在通过基类引用捕获时,可以调用子类重写的what函数,生成不同的报错信息。

模拟发送函数

void send() { string mes; cin >> mes; for (int i = 0; i < 2; i++) { try { if (rand() % 3 == 0) { throw Amod("网络不稳定", 102, mes); } if (rand() % 3 == 1) { throw Amod("不是对方好友", 103, mes); } cout << "成功" << endl; break; } catch (const basemod& b) { if (b.getid() == 102) { if (i == 1) throw; cout << "第" << i + 1 << "次尝试" << endl; } else { throw; } } } }
  • 假如我们发送可能遇到两种报错:网络不好以及不是对方好友。

  • 网络不好就尝试重新发送,再不行才抛出;不是对方好友则直接抛异常。

  • 因此执行循环,当没有报错直接break,有报错则进入catch (const basemod& b)处理,并根据情况继续抛出。

  • 同时,其它模块也可以继承基类,抛出对应的异常。

4. 安全问题

  • 在抛出异常后,后面的代码不再执行,可能导致内存释放不会进行。

  • 解决方式:使用智能指针。

5. 异常规范

  • C++98:如果一个函数不会抛出异常,就在声明后加throw()(跟空括号)。

  • C++11:加noexcept

  • 但由于noexcept可能与实际异常捕获冲突,且编译器不会严格检查,因此要避免写这种有冲突的代码。

  • 同样,noexcept可以检查这个函数是否会抛异常。

cout << noexcept(func()) << endl; int t = 0; cout << noexcept(t++) << endl;
  • 可能会抛异常的函数返回 0,否则返回 1。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/15 7:06:00

DamoFD模型微调教程:让检测器认识你的特殊人脸类型

DamoFD模型微调教程&#xff1a;让检测器认识你的特殊人脸类型 你是不是也遇到过这种情况&#xff1a;团队做的是动画项目&#xff0c;角色都是卡通风格的&#xff0c;结果用现成的人脸检测模型一跑&#xff0c;根本识别不出这些“非真实”的人脸&#xff1f;明明图里有脸&…

作者头像 李华
网站建设 2026/2/10 0:13:15

阿里开源万物识别模型卡顿?GPU算力优化实战案例详解

阿里开源万物识别模型卡顿&#xff1f;GPU算力优化实战案例详解 1. 业务场景与性能痛点 在当前多模态AI快速发展的背景下&#xff0c;图像识别技术已广泛应用于内容审核、智能搜索、自动化标注等场景。阿里近期开源的“万物识别-中文-通用领域”模型&#xff0c;凭借其对中文…

作者头像 李华
网站建设 2026/2/15 17:20:15

零基础教程:手把手教你用vLLM启动DeepSeek-R1轻量化大模型

零基础教程&#xff1a;手把手教你用vLLM启动DeepSeek-R1轻量化大模型 本教程将带你从零开始&#xff0c;在本地环境中使用 vLLM 成功部署并运行 DeepSeek-R1-Distill-Qwen-1.5B 轻量化大模型。无论你是AI初学者还是希望快速搭建推理服务的开发者&#xff0c;本文都提供了完整…

作者头像 李华
网站建设 2026/2/14 5:12:53

亲测DeepSeek-R1 1.5B:CPU推理效果超预期

亲测DeepSeek-R1 1.5B&#xff1a;CPU推理效果超预期 在当前大模型普遍依赖高性能GPU进行推理的背景下&#xff0c;一款能够在纯CPU环境流畅运行、同时保留强大逻辑推理能力的小参数模型——DeepSeek-R1 (1.5B)&#xff0c;无疑为本地化AI应用带来了新的可能性。本文基于实际部…

作者头像 李华
网站建设 2026/2/15 15:00:41

Qwen3-4B-Instruct保姆级教程:模型微调与定制

Qwen3-4B-Instruct保姆级教程&#xff1a;模型微调与定制 1. 引言 1.1 学习目标 本文旨在为开发者提供一份完整、可落地的 Qwen3-4B-Instruct 模型微调与定制化部署 实践指南。通过本教程&#xff0c;您将掌握&#xff1a; 如何基于 Hugging Face 和 Transformers 框架加载…

作者头像 李华
网站建设 2026/2/16 9:46:37

wl_arm入门必看:零基础快速理解嵌入式开发核心要点

从点亮一个LED开始&#xff1a;零基础吃透wl_arm嵌入式开发你有没有过这样的经历&#xff1f;手握一块写着“wl_arm”的开发板&#xff0c;电脑上装好了Keil或STM32CubeIDE&#xff0c;看着示例工程里那串HAL_GPIO_TogglePin()代码&#xff0c;心里却在发问&#xff1a;“这行代…

作者头像 李华