You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++中按基类引用捕获派生类异常为何仍出现切片问题?

问题根因

首先要纠正你的误解:你的代码并没有发生对象切片,问题出在what()函数的签名不匹配,没有正确实现基类虚函数的覆盖。

  • C要求派生类要覆盖基类的虚函数,函数签名必须和基类完全一致。std::exception中what()的标准签名是 virtual const char* what() const noexcept(C11之前为virtual const char* what() const throw())。
  • 你在bad_hmean里定义的what()为 const char *what(),缺少了const修饰符,这不是对基类虚函数的覆盖,只是一个和基类同名的非虚成员函数,只会隐藏基类的同名函数。

不同捕获方式的行为差异

  • 当你用std::exception& e捕获异常时,变量的静态类型是std::exception,编译器查找what()时会调用基类的虚函数实现,也就是你初始化std::logic_error时传入的字符串BAD HARMONIC MEAN VALUES。
  • 当你用bad_hmean&捕获异常时,变量的静态类型是bad_hmean,编译器会直接调用你定义的非虚what()函数,输出拼接好的预期内容。
修复方案

修改bad_hmean的what()函数签名,和基类保持一致即可,建议额外加override关键字,让编译器在签名不匹配时直接报错,提前规避这类问题:

const char *what() const noexcept override { return what_; }

另外你的实现还存在内存安全风险:抛出异常时会生成异常对象的拷贝,默认拷贝构造函数只会拷贝what_指针,会导致多个对象指向同一块堆内存,最终触发double free。建议改用std::string存储报错内容,避免手动管理内存。


内容的提问来源于stack exchange,提问作者Nikola Vugdelija

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 21:24:03