【问题标题】:Can't catch class derived from std::exception by reference to std::exception无法通过引用 std::exception 来捕获从 std::exception 派生的类
【发布时间】:2018-05-02 11:16:55
【问题描述】:

我创建了一个派生自 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 构造函数,也会发生同样的事情。通常解决方案是只使用异常捕获,但在我的原始代码中,我需要捕获不同类型的异常,所有这些异常都继承自 std::exception。为什么会这样?通过引用基地捕获不起作用吗?如何使用一个 catch 块捕获源自 std::exception 的所有异常?

【问题讨论】:

    标签: c++ exception polymorphism


    【解决方案1】:

    当您在定义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;
                   ^
    

    live example on wandbox.org


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

    class Exception : public std::exception
    

    ...您的原始代码将起作用。

    live example on wandbox.org


    1[dcl.init.ref][conv.ptr]

    2 除非您在derived 本身的范围内。看到这个live example on wandbox.org

    【讨论】:

    • 也可以从friendderived 中捕获Exception 作为std::exception
    • @Peter 可能是朋友,是的,但不是派生的。至少需要保护继承。
    • 不错的答案+10。谢谢。
    【解决方案2】:

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

    class Exception : public std::exception
    

    那么你的output就是

    test
    

    有关此主题的更多详细信息,请参考Difference between private, public, and protected inheritance

    【讨论】:

    • 很高兴解释为什么这不适用于私有继承
    猜你喜欢
    • 1970-01-01
    • 2019-05-23
    • 1970-01-01
    • 1970-01-01
    • 2020-02-16
    • 1970-01-01
    • 2015-04-17
    • 2011-04-16
    • 1970-01-01
    相关资源
    最近更新 更多