c++ - 如何从 std::exception 到 std::nested_exception 的 dynamic_cast?
问题描述
我刚刚看到一个包含 dynamic_cast from std::exception
to的代码std::nested_exception
,例如,
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
这对于and来说是不是很特别std::nested_exception
?或者,我可以在对象dynamic_cast<A&>(b)
类型A
和类型b
没有共同基类的情况下成功吗?
解决方案
一开始,我认为这段代码不会被编译,因为 std::nested_exception 不是从 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
};
预期的 dynamic_cast 会对继承进行静态检查,但我错了
在上述情况下,必须在运行时dynamic_cast
检查您是否真的是 a ,在这种情况下它也是a 。std::exception
MyExceptionWrapper
std::nested_exception
这就是为什么它被称为动态转换,因为它必须在运行时检查动态类型。如果您想在编译时执行静态检查,您正在寻找静态转换。
虽然我找不到明确提到 dynamic_cast 允许这样做的相关标准规范
这都是有据可查的。我们正在讨论链接页面中的以下条款:
- 5) 如果 expression 是指向多态类型 Base 的指针或引用,并且 new_type 是指向 Derived 类型的指针或引用,则执行运行时检查:
(注意Base=std::exception
是多态的)
- b) 否则,如果表达式指向/引用最派生对象的公共基类,并且同时,最派生对象具有 Derived 类型的明确公共基类,则转换的结果指向/引用派生对象(此被称为“边播”。)
由于您在编译时无法判断 astd::exception&
不是真正的 a MyExceptionWrapper
,因此您必须在运行时执行此操作。
PS。如果您想避免在catch
块内意外重新抛出,只需编写
auto *nested = dynamic_cast<std::nested_exception*>(&e);
反而。然后你可以检查nullptr
它是否成功。
聚苯乙烯。正如 Sean 所暗示的,MyExceptionWrapper
上面确实更有可能是由 生成的类型throw_with_nested
,但它具有相同的效果。
推荐阅读
- excel - 根据内容隐藏行 - 速度
- django - create multiple related object with Django REST Framework
- c - C中的胖指针
- python-2.7 - OpenCV 函数 cv2.fillpoly() 是如何工作的
- html - Angular 6 是否正在删除默认元素边距?
- elasticsearch - Elasticsearch 6.2.3 无法解析日期字段
- c# - 我正在尝试使用 myCommand.Parameters.Add() 从我的数据库中读取数据,但它返回 0 结果
- python - tf.train.write_graph 使用所有内存并导致 MemoryError
- java - 如何使用 RESTEasy 显示浏览器登录表单以进行基本身份验证
- javascript - CSS bg-img 涵盖“第一次看/访问”