You need to enable JavaScript to run this app. C++自定义继承std::exception的异常类:为何按值捕获显示Unknown exception,引用捕获正常?
优惠活动
大模型
产品
解决方案
定价
更多

C++自定义继承std::exception的异常类:为何按值捕获显示Unknown exception,引用捕获正常?

核心原因:按值捕获时触发对象切片(Object Slicing),破坏了原异常对象的类型完整性

两种捕获方式的底层行为差异

  • 按值捕获的实际执行逻辑
    执行throw MyException("This is an exception")时,抛出的是包含std::exception基类子对象、以及自定义string exc派生类成员的完整MyException实例。
    当catch子句写为catch (const std::exception exc)时,编译器不会将原异常对象直接传入catch块,而是调用std::exception的拷贝构造函数,仅拷贝原MyException对象中属于std::exception基类的那部分成员,生成一个全新的纯std::exception类型临时对象作为catch块内的exc变量。
    这个过程会直接丢弃所有属于MyException派生类的成员——也就是存储自定义提示字符串的exc变量。此时调用exc.what()时,实际执行的是这个纯std::exception对象自带的默认what()实现,而标准库中std::exception的默认what()返回值就是Unknown exception,正好对应你观察到的测试结果。
    这种场景下不存在虚函数动态绑定的空间:因为exc已经是实打实的std::exception类型实体对象,而非指向派生类的引用或指针,调用what()会完全静态绑定到std::exception的默认实现,和MyException的重写逻辑没有任何关联。
  • 引用捕获的实际执行逻辑
    当catch子句写为catch (const std::exception &exc)时,编译器不会生成任何拷贝对象,exc仅作为一个指向原抛出的完整MyException对象的const基类引用存在。
    由于std::exception的what()方法本身是虚函数,通过基类引用调用虚方法时会触发动态绑定,实际执行MyException类中重写的what()逻辑,自然可以正确读取MyException对象里存储的自定义提示字符串,返回传入的This is an exception内容。

相关注意事项

  • C++异常处理的标准最佳实践明确要求,捕获异常时必须使用引用(或指针)类型承接,按值捕获本身就是非推荐写法:既会产生不必要的拷贝开销,也极易触发上述对象切片问题,丢失异常携带的自定义信息。
  • 你当前的MyException实现存在潜在隐患:构造函数没有显式调用std::exception基类的构造函数,虽然std::exception提供默认构造不会触发编译错误,但如果后续切换到需要向std::exception传递初始化参数的标准库实现版本,可能会出现基类成员初始化不一致的问题。

内容的提问来源于stack exchange,提问作者BattleTested_закалённый в бою

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.01 19:06:08