如果我们编写对 dynamic_cast 的调用并返回到指针值的原始类型,C++ 是否保证保留该值,假设没有 dynamic_cast 失败,即不返回 nullptr?
我查看了 https://www.cprogramming.com/tutorial/virtual_inheritance.html 中的“虚拟继承中的内存布局”部分.这让我对如何实现它有了一个不错的想法。从它的外观来看,似乎不可能获得不同的地址。然而,这只是一个这样的实现,我只是想确保没有符合规范的实现可以返回与原始地址不同的地址。
#include <cassert>
struct A { virtual ~A() {} };
struct B : virtual public A {};
struct C : virtual public A {};
struct D : public B, public C {};
int main()
{
B* b = new D();
C* c = dynamic_cast<C*>(b);
if (c != nullptr)
{
B* bp = dynamic_cast<B*>(c);
assert(bp == b); // Will this assert ever fire?
}
return 0;
}
更一般的情况:
A* a = ...
dynamic_cast<A*>(dynamic_cast<B*>(...(a)...)) is `a` or nullptr
我用 gcc8 和 clang9 运行了上面的代码,它们没有触发断言。
最佳答案
Does side-casting to and from sibling types preserve addresses in C++?
动态转换产生一个指向基础/派生对象的指针,并且该对象只有一个地址。这适用于侧面抛投和向下抛投。
请注意,如果由于具有多个相同类型的非虚拟基而使基不明确,则侧投可能会失败。您的示例没有这种歧义。在这种情况下,将返回 null。
Can any operation change the layout of the object during run-time?
没有。所有对象的布局在创建时就已确定。在标准 C++ 中,所有类型的布局在编译时就已经确定,尽管有语言扩展,例如灵活数组成员,可以放宽这一点。
关于c++ - 与兄弟类型之间的侧向转换是否保留 C++ 中的地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58223607/