只要指向基类型的指针实际上指向派生类型的实例,那么根据 C++ 标准,这种用法就不是未定义的。但是,在您的代码示例中,指针b
不指向的实例B
或其任何派生类型(没有),它指向的实例A
。因此,您的代码实际上确实调用了未定义的行为。
我在 SO 上找到了一个答案,说它可以导致 UB,对其进行测试,它既可以编译又可以正常工作。
某些代码编译并正常工作的事实并不排除代码调用未定义行为的可能性,因为未定义行为包括“似乎可以工作”。您应该避免未定义行为的原因是因为无法保证下次调用 UB 时它会以相同的方式工作。
它是未定义的行为吗?如果是解决这个问题的正确方法是什么?
在您的示例中,是的,这是未定义的行为。正确的方法取决于您的代码实际上应该做什么,因为您提供的示例充其量只是一个学术示例。
为了清楚起见,对main()
函数的以下修改具有明确定义的行为,并且 C++ 标准明确允许:
B objectB;
A* ptrA = &objectB;
B* b = static_cast<B*>(ptrA);
b->Show();
在这里,它的定义很好,因为指针ptrA
实际上指向 的实例B
,即使指针本身具有 type A*
。在上面的示例中,将 fromA*
转换为然后在转换的指针上B*
调用 's 函数之一将起作用。B
不同之处在于,在您问题的示例中,b
实际上并不指向B
.
相关条款(强调我的):
C++ 标准 5.2.9/8 静态转换 [expr.static.cast]
如果从“ pointer to _ _ _ ” 到“指向 ” 的指针存在B
B
D
D
B
D
B
(4.10),cv2与cv1具有相同的
cv限定或大于cv限定,并且不是 的虚拟基类。空指针值 (4.10) 被转换为目标类型的空指针值。如果“指向 cv1 的指针”类型的右值指向B
D
B
B
那实际上是 type 对象的子对象D
,结果指针指向 type 的封闭对象D
。否则,强制转换的结果是未定义的。