如果我参考基类捕获它,为啥我的异常会被切分到基类?
Posted
技术标签:
【中文标题】如果我参考基类捕获它,为啥我的异常会被切分到基类?【英文标题】:Why is my exception sliced to base class if I catch it with reference to base class?如果我参考基类捕获它,为什么我的异常会被切分到基类? 【发布时间】:2021-11-23 16:29:53 【问题描述】:所以我写了一个小的 C++ 类如下:
class bad_hmean : public std::logic_error
const char *nature_;
char *what_;
public:
bad_hmean(const char *fname);
~bad_hmean() delete[] what_;
const char *what() return what_;
;
inline bad_hmean::bad_hmean(const char *fname):nature_("BAD HARMONIC MEAN VALUES"), std::logic_error("BAD HARMONIC MEAN VALUES")
int len = strlen(fname) + strlen(nature_)+3;
what_ = new char [len];
strcpy(what_, fname);
strcat(what_, ": ");
strcat(what_, nature_);
我已经尝试在以下主目录中对其进行测试:
void fun1() throw bad_hmean(__func__);
int main()
try
fun1();
catch(std::exception& e)
std::cout << e.what();
当我运行它时,我遇到了一个我无法解决的问题。即使我按值抛出异常并通过引用捕获它,切片仍然发生,因为我的代码输出是:BAD HARMONIC MEAN VALUES。 但是,如果我将异常捕获为对 bad_hmean 的引用,则输出就是我想要的: fun1:不好的谐波平均值。
有人知道为什么会这样吗?
【问题讨论】:
what() 是虚函数,因此应该正确调用它,因为它是绑定到具有虚表的对象而不是静态的。它在 std::exception 类中被声明为虚拟。 如果异常类bad_hmean
被复制(并且需要复制异常),那么您将遇到双重破坏问题(因为类中断 The Rule of Three)。轻松修复 - 用 std::string 替换手动管理的 c-string。首选修复 - 将异常类替换为 std::runtime_error
或您自己的从 std::runtime_error
派生的类
【参考方案1】:
bad_hmean
没有正确覆盖 what()
。它应该与基类what
的签名匹配为:
const char *what() const noexcept return what_;
// ^^^^^ ^^^^^^^^
顺便说一句:最好使用override
specifier(C++11 起)来确保函数覆盖基类中的虚函数。例如
const char *what() const noexcept override return what_;
【讨论】:
哦,你是对的。我以后会更聪明,让IDE为我自动完成虚拟功能。非常感谢。以上是关于如果我参考基类捕获它,为啥我的异常会被切分到基类?的主要内容,如果未能解决你的问题,请参考以下文章