两个派生类之间的转换

use*_*208 5 c++ casting class

在具有共同祖先的类上的指针之间进行转换是否合法?编译器是否注意到这种层次结构并确保其安全(调用 1)?或者用户是否必须手动遍历层次结构才能始终安全(调用 2)?

说我们有

class A{};
class B:A{};
class C:A
{ 
public:
 int SomeFunc(){return 3;}
};

int _tmain(int argc, _TCHAR* argv[])
{
    B* b = (B*)((A*)new C()); // this is done manually, i believe it is safe

  ((C*)b)->SomeFunc(); // is this safe? this is the cast in question

  return ((C*)((A*)b))->SomeFunc(); // this is done manually, i believe it is safe
}
Run Code Online (Sandbox Code Playgroud)

编辑:使该代码可编译且可运行

edit2:添加了更多评论

Col*_*mbo 2

B* b = (B*)((A*)new C()); // this is done manually, i believe it is safe\n
Run Code Online (Sandbox Code Playgroud)\n\n

这不安全。\n粗略地说, expr
形式的强制转换被转换为or 。[expr.cast]/4:(T) static_castreinterpret_cast

\n\n
\n

执行的转换

\n\n
    \n
  • ( 5.2.11 const_cast),
  • \n
  • ( static_cast5.2.9),
  • \n
  • 一个static_cast后接一个const_cast,
  • \n
  • a reinterpret_cast(5.2.10),或
  • \n
  • 一个reinterpret_cast后接一个const_cast,
  • \n
\n\n

可以使用显式类型转换的强制转换表示法来执行。\n 相同的语义限制和行为适用[\xe2\x80\xa6]
如果可以用上面列出的\n 多种方式解释\n 转换,则使用列表中第一个出现的解释,即使该解释产生的强制转换格式不正确。

\n
\n\n

您可以忽略const_cast这里,因为您的代码中没有完成任何限定转换。\nstatic_cast两种转换都足够,第一个转换为 ,(A*)第二个转换为 。(B*)\n第一个转换就很好。升级从来都不是问题。
\n第二个会引发未定义的行为。[expr.static.cast]/11:

\n\n
\n

类型为 \xe2\x80\x9c 的纯右值,指向cv1 B,\xe2\x80\x9d ,其中B是类类型,\n 可以转换为类型为 \xe2\x80\x9c 的纯右值,指向cv2 D \xe2\x80\x9d,其中\n D是从 派生的类(第 10 条)B,如果存在从 \xe2\x80\x9cpointer 到D\xe2\x80\x9d 到 \xe2\x80\x9cpointer 到B\xe2\x80\x9d 的有效标准\n 转换( 4.10),\n cv2 与 cv1具有相同的 cv 限定,或比cv1更高的 cv 限定,并且B既不是 的虚拟基类D,也不是 的虚拟基类的基类D。[\xe2\x80\xa6]如果\n \xe2\x80\x9c 类型的纯右值指向 cv1 B\xe2\x80\x9d 指向的 aB实际上是类型 的\n 对象的子对象D,则结果指针指向到类型的封闭\n对象D。否则,转换的结果是未定义的。

\n
\n\n

另请注意,仅仅因为static_cast触发 UB 并不意味着它未被选中(并被替换为reinterpret_cast)。

\n\n

第二个和第三个强制转换基于第一个强制转换(这会导致未定义的行为),因此谈论它们的有效性是没有意义的。

\n