C++ catch作用域内抛出派生类未被捕获的问题原因及修复
问题原因
- C++的异常捕获遵循作用域匹配规则:一组
catch仅能捕获其前面对应try代码块内抛出的异常。你代码中throw PE是在第一个catch块内部触发的,已经脱离了外层try的作用范围,同层级后续的catch (subEx e)不会响应该异常,异常会直接向上层栈展开寻找匹配的异常处理逻辑,没有对应处理就会触发程序强制终止。 - 额外补充:即便你调换两个
catch的顺序,把派生类的catch放在基类前面,也解决不了本次问题,核心原因是捕获范围不匹配。
修复方案
调整为嵌套try-catch结构,让内层catch抛出的异常可以被外层catch捕获,同时修复原代码的内存泄漏、析构逻辑缺失问题,可正常运行的代码如下:
#include <iostream> #include <string> using namespace std; class myEx { int errNum; public: myEx(int e) : errNum(e) {} virtual void printErr() { cout << errNum << " "; } virtual ~myEx() {} // 新增虚析构函数,保证基类指针释放子类对象时逻辑正确 }; class subEx : public myEx { string errDesc; public: subEx(int e, string d) : myEx(e), errDesc(d) {} void printErr() override { myEx::printErr(); cout << errDesc << " "; } }; int main() { try { try { myEx* pME = new subEx(0, "err 0"); throw pME; } catch (myEx* p) { p->printErr(); delete p; // 释放动态申请的内存,解决内存泄漏 subEx PE(1, "err 1"); throw PE; } } catch (const subEx& e) // 用const引用捕获避免对象拷贝,效率更高 { e.printErr(); } return 0; }
核心修改点
- 新增外层
try块包裹原有整段逻辑,把原来的第二个catch移动到外层try对应的捕获位置,匹配内层catch抛出的subEx对象 - 补充基类虚析构函数和内存释放逻辑,避免内存泄漏
- 调整
subEx捕获改用printErr新增override关键字,提升代码可读性与可维护性
内容的提问来源于stack exchange,提问作者Ronyco123
相关产品推荐
相关产品推荐

