其他分享
首页 > 其他分享> > c – 如何从std :: exception动态广播到std :: nested_exception?

c – 如何从std :: exception动态广播到std :: nested_exception?

作者:互联网

我刚刚看到一个包含从std :: exception到std :: nested_exception的dynamic_cast的代码,例如,

try {
    std::throw_with_nested(std::runtime_error("error"));
} catch (std::exception &e) {
    auto &nested = dynamic_cast<std::nested_exception&>(e);
    std::cout << "ok" << std::endl;
}

在第一次,我认为这段代码不会被编译,因为std :: nested_exception不是从std :: exception派生的,我希望dynamic_cast会对继承进行静态检查,但我错了.

虽然我找不到明确提到dynamic_cast允许的相关标准规范,但我确认所有三个主要编译器(clang / gcc / msvc)都允许完全不相关的类型之间的dynamic_cast.

但是,std :: nested_exception不是从std :: exception派生的,所以我认为dynamic_cast会抛出bad_alloc异常并且“ok”从不打印.我又错了.

现在,我想知道这是如何工作的.对于std :: exception和std :: nested_exception,这是一个特殊和特殊的东西吗?或者,我可以创建另一个成功的dynamic_cast< A&>(b)其中类型A和对象类型b没有公共基类?

解决方法:

At the very first time, I thought this code won’t be compiled because std::nested_exception is not derived from std::exception

这还不够 – std :: nested_exception旨在用作mixin类,比如

struct MyExceptionWrapper: public std::exception, std::nested_exception
{
    // an 3rd-party component of my library threw
    // and I want to wrap it with a common interface
};

expected dynamic_cast would do static check of inheritance but I was wrong

在上面的例子中,dynamic_cast必须在运行时检查你的std :: exception是否真的是一个MyExceptionWrapper,在这种情况下它也是一个std :: nested_exception.

这就是它被称为动态强制转换的原因,因为它必须在运行时检查动态类型.如果要在编译时执行静态检查,则需要进行静态转换.

Although I couldn’t find related standard specification which explicitly mentions that dynamic_cast allows this

这都是well documented.我们正在讨论链接页面中的以下条款:

  • 5) If expression is a pointer or reference to a polymorphic type Base, and new_type is a pointer or reference to the type Derived a run-time check is performed:

(注意Base = std :: exception是多态的)

    • b) Otherwise, if expression points/refers to a public base of the most derived object, and, simultaneously, the most derived object has an unambiguous public base class of type Derived, the result of the cast points/refers to that Derived (This is known as a “sidecast”.)

因为你无法在编译时告诉std :: exception&实际上并不是MyExceptionWrapper,你必须在运行时这样做.

PS.如果你想避免在catch块内意外重新抛出,那就写吧

auto *nested = dynamic_cast<std::nested_exception*>(&e);

代替.然后你可以检查nullptr以确定它是否成功.

PPS.正如Sean所说,上面的MyExceptionWrapper实际上更可能是throw_with_nested生成的类型,但它具有相同的效果.

标签:dynamic-cast,c,c11,exception,nested-exceptions
来源: https://codeday.me/bug/20190828/1747603.html