无法通过引用 std::exception 来捕获从 std::exception 派生的类

Can't catch class derived from std::exception by reference to std::exception

本文关键字:std exception 派生 引用      更新时间:2023-10-16

我创建了一个派生自 std::exception 的自定义异常类。

#include <iostream>
class Exception : std::exception {
public:
const char* what() const noexcept override {
return "test";
}
};
int main() {
try {
throw Exception();
} catch (std::exception& e) {
std::cout << e.what() << std::endl;
}
}   

该程序在 Ubuntu 上由g++ -stdc++=17编译时,会导致异常不会被catch块捕获,即使通过引用捕获也应该捕获派生的异常。它调用std::terminate,即使它发生在一个通过引用捕获其基类的try块中。如果Exceptionstd::runtime_error继承并"test"传递给其自己的构造函数中的std::runtime_error构造函数,也会发生同样的事情。通常解决方案是仅使用Exception捕获,但是在我的原始代码中,我需要捕获不同类型的异常,所有这些异常都继承自std::exception。为什么会这样?参考基地捕捉不起作用吗?如何使用一个 catch 块捕获从std::exception派生的所有异常?

在定义基类期间从基类继承class时,继承的默认访问修饰符是private。这意味着以下两个定义是等效的:

class derived : base { /* ... */ };
class derived : private base { /* ... */ };

该语言不允许1U 引用来自私有基2的派生类。例如,以下代码不编译:

int main()
{
derived d;
base& b = d; // <== compilation error
}
error: 'base' is an inaccessible base of 'derived'
base& b = d;
^

wandbox.org 上的现场示例


这就是您的catch块无法处理Exception的原因。将您的继承更改为public...

class Exception : public std::exception

。并且您的原始代码将起作用。

wandbox.org 上的现场示例


1参见 [dcl.init.ref] 和 [conv.ptr]。

2除非你属于derived本身的范围。请参阅wandbox.org 上的这个实时示例

你需要公开派生自std::exception

class Exception : public std::exception

那么你的输出是

test

有关本主题的更多详细信息,请参阅私有、公共和受保护继承之间的区别。