繁体   English   中英

什么时候是`static_cast <Base*> (的static_cast <void*> (派生))`从指向派生类的指针有效吗?

[英]When is a `static_cast<Base*>(static_cast<void*>(derived))` from a pointer to a derived class valid?

对于这个问题,不应涉及多态,即没有虚方法,也没有虚基类。 万一重要,我的案子不涉及任何这些。

假设我有一个Derived类,它有一个类型为Base的明确可访问父类,没有多态(没有虚方法,没有虚基类),但可能涉及间接和/或多重继承。 进一步假设我有个有效的指针Derived *derived (指向类型的对象Derived或其亚类)。

在这种情况下,我相信static_cast<Base*>(derived)是有效的(产生有效的可用指针)。 BaseDerived之间的祖先链涉及多重继承时,此static_cast可能意味着指针调整以在Derived实例中定位Base实例。 为此,编译器需要知道继承链,在这种情况下他会这样做。 但是,如果插入了void *的中间转换,则会从编译器中隐藏该继承链信息。 对于哪个继承链是这样的静态转换有效吗? 我期待以下之一:

  • 一个都没有? 除非指针确实指向确切类型,否则从void指针访问static_cast是未定义的行为。
  • 对于没有多重继承的所有链? 然后,编译器可以保证Base总是在Derived的开头 - 但标准是什么?
  • 对于在所有中间多重继承链的第一个父类中找到Base的所有链? 也许BaseDerived的开头仍然匹配?
  • 总是? static_cast到void指针总是可以调整到第一个父节点的开头,而static_cast从void指针撤消那个调整。 但是,通过多重继承,“第一个父母”不一定是所有父母的父母。

static_cast<Base*>(static_cast<void*>(derived))在C ++标准中有一个名称。 它被称为reinterpret_cast 它在[expr.reinterpret.cast]第7段中指定:

可以将对象指针显式转换为不同类型的对象指针。 当对象指针类型的prvalue v被转换为对象指针类型“指向cv T的指针”时,结果是static_cast<cv T*>(static_cast<cv void*>(v)) [注意:将“指向T1的指针”类型的prvalue转换为“指向T2的指针”类型(其中T1和T2是对象类型,T2的对齐要求不比T1更严格)并返回其原始类型产生原始指针值。 - 结束说明]

reinterpret_cast是告诉编译器将指针视为其他东西。 编译器可以或将根据此指令进行调整。 如果我们说谎,那么行为就是未定义的。 标准是否说这样的reinterpret_cast有效? 它实际上。 [basic.compound]第4段中定义了指针互换性的概念:

如果出现以下情况,则两个对象a和b是指针可互换的:

  • 它们是同一个对象,或者
  • 一个是union对象,另一个是该对象的非静态数据成员([class.union]),或
  • 一个是标准布局类对象,另一个是该对象的第一个非静态数据成员,或者,如果该对象没有非静态数据成员,则该对象的任何基类子对象([class.mem]) , 要么
  • 存在对象c,使得a和c是指针可互换的,并且c和b是指针可互换的。

如果两个对象是指针可互换的,则它们具有相同的地址,并且可以通过reinterpret_cast从指向另一个的指针获得指向一个对象的指针。 [注意:数组对象及其第一个元素不是指针可互换的,即使它们具有相同的地址。 - 结束说明]

第三个子弹是你的答案。 类层次结构中的对象必须支持限制(从顶部基础到大多数派生的标准布局 ),然后才能保证转换为定义良好的结果。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM