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

问题描述 投票:0回答:2

我创建了一个派生自 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
块中。如果
Exception
继承自
std::runtime_error
并将
"test"
传递给其自己的构造函数中的
std::runtime_error
构造函数,也会发生同样的情况。通常,解决方案是仅使用
Exception
进行捕获,但在我的原始代码中,我需要捕获不同类型的异常,所有这些异常都继承自
std::exception
。为什么会出现这种情况?通过引用基数进行捕获不起作用吗?如何使用一个 catch 块捕获源自
std::exception
的所有异常?

c++ exception polymorphism
2个回答
10
投票

在定义

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

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

该语言不允许1您从私有基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 上的这个 现场示例


4
投票

您需要公开源自

std::exception

class Exception : public std::exception

那么你的输出

test

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

© www.soinside.com 2019 - 2024. All rights reserved.