【发布时间】:2019-04-05 08:43:28
【问题描述】:
看看简单的例子:
struct Base { /* some virtual functions here */ };
struct A: Base { /* members, overridden virtual functions */ };
struct B: Base { /* members, overridden virtual functions */ };
void fn() {
A a;
Base *base = &a;
B *b = reinterpret_cast<B *>(base);
Base *x = b;
// use x here, call virtual functions on it
}
这个小 sn-p 有未定义的行为吗?
reinterpret_cast 定义明确,它返回不变的值base,只是类型为B *。
但我不确定Base *x = b; 行。它使用b,它的类型为B *,但它实际上指向一个A 对象。而且我不确定,x 是否是“正确的”Base 指针,是否可以用它调用虚函数。
【问题讨论】:
-
我不认为强制转换本身会导致 UB,但是尝试使用
b调用虚函数或使用B只有成员肯定会导致 UB。认为x是安全的。 -
@Someprogrammerdude:是的,问题是,“尽管认为
x是安全的”是真是假。我有一种感觉,虽然这乍一看似乎是无害的(这是一个无操作),但它是 UB。 -
reinterpret_cast无法在基类和派生类指针/引用之间安全地转换。b不能保证是一个有效的指针。你可以用它做的唯一安全的事情是 reinterpret_cast 它回到原来的类型。 -
@n.m.:假设您将
b转换回reinterpret_cast。它应该给你一个正确的Base指针。现在,reinterpret_cast只不过是转换为void *,然后转换为Base *。我的示例代码做了类似的事情(它只是没有转换为void *,并且转换为Base *是隐式的,而不是通过static_cast)。无论如何,我只是在这里扮演魔鬼的拥护者。我知道转换是 UB,但不能用标准备份。 -
似乎关于隐式派生到基指针转换的行:
The result of the conversion is a pointer to the base class subobject of the derived class object.(timsong-cpp.github.io/cppwp/conv.ptr#3),意味着我们确实取消了b的引用,因此点击了 UB。
标签: c++ language-lawyer