【问题标题】:C++ Standard On The Address of Inherited Members关于继承成员地址的 C++ 标准
【发布时间】:2015-02-10 17:40:28
【问题描述】:

C++ 标准对继承成员的地址有什么规定吗?例如,如果我继承了一个 int 成员或非虚拟方法,它是否说明了它的地址或虚拟成员:如果我不覆盖它,如果我这样做?构造函数,如果我使用以前的构造函数?运算符、重载运算符、模板成员?它是否说明了这些事情?

【问题讨论】:

  • 这个问题有点混乱。它们中的大多数是实现定义的。你有任何代码或你想要达到的目标吗?
  • 标记为该问题重复的问题并不是真正的重复。它只处理 v-table 部分。它没有解决 OP 提出的其他问题 - 成员变量和非虚拟方法的地址。

标签: c++ c++11 inheritance standards memory-address


【解决方案1】:

标准,第 1.8 节是关于 C++ 对象模型的。

不多说:对象是一个内存区域(但它可能包含用于对齐目的的未使用区域)并且可以包含子对象(成员子对象或基类子对象,或数组子对象)。从完整对象的定义中,您可以推断出子对象包含在其对象的内存区域中。它说两个既不是位域也不是基类子对象的不同对象应具有不同的地址。

第 9.2/15 节提供了一些关于对象内地址顺序的附加信息:

具有相同访问权限的(非联合)类的非静态数据成员 分配控制权,以便后面的成员拥有更高的 类对象中的地址。非静态的分配顺序 未指定具有不同访问控制的数据成员。 实现对齐要求可能会导致两个相邻的成员 不得紧随其后分配;所以可能 管理虚拟功能的空间要求和 虚拟基类。

当所有联合成员都是以相同类型序列开头的结构时,有几句话是关于联合的。然后允许“检查公共部分”,从中您可以推断它们必须具有相同的地址。

最后,我在 9.2/21 找到了最后一个:

一个指向标准布局结构对象的指针,使用 reinterpret_cast 适当转换,指向它的初始成员(或者如果 member 是一个位域,然后是它所在的单元),反之亦然 反之亦然。

基本上,就是这样。你会看到这里有很多实现定义的东西,关于每个对象的确切布局。

不幸的是,对于基类子对象及其派生对象的地址,您甚至不能说太多:也可能存在多重继承。因此该标准不使用地址假设:它宁愿声明如下内容:“如果基类可访问,则可以将指向派生类的指针隐式转换为指向该基类的指针”

【讨论】:

  • 感谢您的回答!对于两个既不是位域也不是基类子对象的不同对象的部分,这是否意味着基类在继承时具有不同的地址(例如,它在内部就像一个数据成员?)?
  • 我刚刚编辑解释了基础对象和派生对象之间的关系情况。基本上,编译器知道如何将一个地址转换为另一个地址(通常是相同的地址),但你不能做出假设。如果您恢复“如果位域和基址都没有,则必须具有不同的地址”的确认,您将获得“位域或基址都可能具有相同的地址(但不能保证)。
  • 非常感谢! :-)
猜你喜欢
  • 1970-01-01
  • 2018-12-19
  • 2012-02-13
  • 1970-01-01
  • 2020-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多