如果我参考基类捕获它,为啥我的异常会被切分到基类?

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为我自动完成虚拟功能。非常感谢。

以上是关于如果我参考基类捕获它,为啥我的异常会被切分到基类?的主要内容,如果未能解决你的问题,请参考以下文章

将 PropertyChangedCallback 添加到基类的只读依赖属性

在 C++ 中将派生类对象分配和访问到基类“指向指针”对象

为啥不抽象字段?

将共享指针的派生类切换到基类

使用 autofac 将构造函数注入到基类中

在派生对象中的“this”指针上使用 static_cast 到基类的问题