【问题标题】:Dynamic type of an expression dealing with a base class subobject处理基类子对象的表达式的动态类型
【发布时间】:2019-11-10 17:51:00
【问题描述】:

我再次问这个问题是因为像这样的only other question 已经接近 10 年了,并且包含有关涉及基类子对象的表达式的错误信息:

[defns.dynamic.type] 将泛左值的动态类型定义为:

glvalue 所指的最衍生对象的类型

glvalue 最多只能引用一个对象,并且由于[intro.object] p6 定义的“最衍生对象”本质上是:

类类型的完整对象、数据成员或数组元素,或者非类类型的对象称为最派生对象。

如果glvalue 不引用最派生的对象,那么动态类型会是未定义的吗?

另外,我知道动态类型的表达式的预期效果是:对于泛泛值表达式E,它引用B 类型的对象,它是D 类型的对象的基类子对象,其中BD 的基类,要从E 获取类型D,但是,我看不到当前的措辞如何实现,甚至需要,因为base 的引用/指针绑定到派生类类型的类类型将始终引用基类子对象。据我所知,表达式的类型和它所引用的对象的类型永远不会发生。

【问题讨论】:

  • 什么是“唯一的其他问题”?包含错误信息的问题很自然,那么答案呢?
  • @fore 答案不正确,他们声明对于这个 sn-p:const T& a = U(); 引用绑定到类型为 U 的对象,实际上它绑定到基类子对象创建的临时对象的数量(假设U is derived from T`)
  • @KrystianS:“*当它实际上绑定到创建的临时对象的基类子对象时(假设U 派生自T)*”你能引用实际的位置吗是在标准中说的?因为这不是引用的工作方式。就标准而言,a 是对U 的引用,其类型为T
  • 你能添加一个链接到“唯一的其他问题”吗?

标签: c++ pointers language-lawyer lvalue subobject


【解决方案1】:

如果泛左值不引用最派生的对象,那么动态类型是否是未定义的?

总是这样。因此“then”部分不适用。

根据评论更新

给定

struct foo { };
struct bar : foo { };
const foo& a = bar(); a;

a的动态类型是什么?

答案在page you linked to in your post

[ 示例: 如果静态类型为“指向类B”的指针p 指向从B 派生的类D 的对象,则动态表达式*p 的类型是“D”。参考文献的处理方式类似。 — 结束示例 ]

a 的动态类型是bar,而不是foo

【讨论】:

  • 闪回命题逻辑 101 和实质含义。
  • @Eljay,我不知道这个主题。有趣的主题占据了一个人的灰质。 iep.utm.edu/prop-log.
  • @R Sahu 是吗?以此为例:struct foo { }; struct bar : foo { }; const foo& a = bar(); a; // a refers to the foo subobject of the bar temporary, so the object the glvalue refers to is not a complete object, nor a member, nor an array element, nor an object of non-class type, so how could the dynamic type be the type of the most derived object, if the object that a refers to is not one
  • @KrystianS,在这种情况下,a 的动态类型是bar&
  • @R Shau 我不这么认为,正如 [expr.type] p1 所规定的那样,表示引用的表达式被调整为表示引用表示的对象,表达式的类型是也进行了调整。
【解决方案2】:

我认为您可能会争辩说这是一个措辞缺陷,但这将是迂腐的,因为意图已经很清楚了。而不是:

glvalue 所指的最衍生对象的类型

你可以想象定义是这样的:

glvalue 所指对象的最派生对象的类型

【讨论】:

  • 大多数派生对象不是对象的属性,而是对象可以是的东西,所以我不明白这个措辞有什么意义......无论哪种方式,我都没有看不到一个表达式的类型与它所表示的对象不同的情况。
  • @KrystianS:“无论哪种方式,我都没有看到表达式的类型与它所表示的对象不同的情况。”那么就是这样问题,因为这就是指针和引用在 C++ 中的工作方式。你有一个对象的引用。该引用的类型可以与对象的类型不同(通过基类类型的引用来引用派生类)。但是你总是引用完整的对象。
  • @KrystianS 您应该将“对象的最派生对象”解释为“作为最派生对象的唯一对象,并且要么是所讨论的对象,要么包含它作为基类子对象”。
  • @Nicol Bolas 当您将B 类型的引用绑定到D 类型的对象时,其中BD 的基类,该引用将绑定到基类D 类型对象的子对象,该基类子对象是基类 B 的类型,而不是 D 类型的完整对象。请参阅eel.is/c++draft/dcl.init.ref#5“[...],或者,在任何一种情况下,请参阅对象的适当基类子对象。”。这同样适用于指针,有一个标准的指针转换被应用,参见 [conv.ptr]
  • @KrystianS "引用绑定到 D 类型对象的基类子对象" 不用说!如果子对象的 ptr 和 ref 实际上没有引用子对象,C++ 就没有多大意义。
猜你喜欢
  • 2017-07-19
  • 1970-01-01
  • 1970-01-01
  • 2021-11-17
  • 1970-01-01
  • 2014-04-04
  • 1970-01-01
  • 2021-01-08
  • 2011-04-04
相关资源
最近更新 更多