【问题标题】:C++ Disambiguation: subobject and subclass objectC++消歧:子对象和子类对象
【发布时间】:2013-08-26 19:34:33
【问题描述】:

基本上就是标题所说的。我一直将 Base 对象称为子对象。这是正确的吗?subobject == superclass object 也是正确的吗?哪个更受欢迎?

subclass 表示派生类,subclass object 表示派生类的对象,对吧?

让我感到困惑的是subclass object != subobject

如果这些都是正确的,无论如何..

谢谢

【问题讨论】:

  • 我从未听说过“子对象”或“子类”,但这让我想到了嵌套类或成员变量。在任何情况下,我都不会认为您的意思是“超类”。 “子”!=“超级”。您在哪里找到这些条款?
  • [intro.object]/2 "对象可以包含其他对象,称为子对象。子对象可以是成员子对象、基类子对象或数组元素。"
  • @Mooing 在Virtual Inheritance 上查看此页面它说:“此功能对于多重继承最有用,因为它使虚拟基成为派生类和所有类的公共子对象派生自它。”
  • @DyP:嗯,这表明我错了,以及到目前为止我看到的所有答案。作为答案发布?

标签: c++ inheritance subclass


【解决方案1】:

C++ 标准对子对象 有明确的定义。也就是说,很多人在谈论 C++ 时(准确地说)并没有使用标准的语言。一个流行的例子是术语object。在 Java 等语言中,有些人倾向于仅在 类的实例 的意义上使用 object,这不适用于int。在 C++ 标准中,int 是一个对象。

标准在 [intro.object]/2 中所说的:

对象可以包含其他对象,称为子对象。子对象可以是成员子对象基类子对象或数组元素。不是任何其他对象的子对象的对象称为完整对象

这是在(可能的)内存布局的上下文中理解的。它没有完全指定,但很可能看起来像这样:

class Foo { int i; };
class Bar : public Foo { int j; };

Bar 类型的对象在内存中可能如下所示:

+-酒吧-------------------+ | +-Foo-----+ | | |诠释我 |诠释 j; | | +---------+ | +------------------------+

Foo 的成员是Bar 的成员,就像Bar 的直接成员一样。因此,Bar 的每个对象都“包含”Foo 类型的对象。还要考虑

Bar b;
Bar* pBar = &b;
Foo* pFoo = &b;
+-酒吧-------------------+ | +-Foo-----+ | | |诠释我 |诠释 j; | | +---------+ | +--^--------------------+ ^ |pFoo |pBar

为了允许pFoo 指向Foo 类型的完整对象和Foo 类型的子对象,需要有一个完整且(内存方面)独立的Foo 类型的对象内部的任何对象输入Bar。在编译时可能不知道是哪种情况,但为pFoo->i = 5; 生成的代码必须同时适用于这两种情况。

这一切都是在 as-if 规则下指定的,即它不必是那样的,但它必须以可观察的方式表现。此外,这不是实际的内存布局,但它是一个常见的实现。


在 [intro.object]/4 中

如果完整的对象、数据成员或数组元素是类类型,则其类型被认为是最派生类,以区别于任何基类子对象的类类型;最派生类类型或非类类型的对象称为最派生对象

除了supersedesuperset 之外,标准中没有使用super 这个词。有基类派生类(还有~对象)。


在 C++ 语言标准之外,术语超类用来指代一个基类,而术语子类用来指代到一个派生类。这指的是面向对象的概念和分类,就像物种是生物学中的子类别。

但是在这个分类中,没有内存布局,因此没有必要谈论子对象。有 instancesobjects(在 OO 意义上),所以你可以谈论 超类的对象子类的对象。混淆可能源于将这个 子类的对象 缩写为 subobject,并将 OO 语言与 C++ 标准中的语言混合。

【讨论】:

  • 谢谢,这似乎是彻底和正确的,我已将其标记为这样。只是好奇,如果在谈话中提到Bar 中的Foo,你会如何亲自提及?
  • @user2672807 我会称他们为metasyntactic variables ;) 其余的取决于上下文。由于 C++ 支持多重继承和私有继承,当主题是 C++ 而不是一般的 OO 时,我更喜欢使用 基类派生类
  • 啊。好吧,我指的是一个类的实例,即一个对象。您认为将派生对象的基本部分称为base object 是否可以接受或正确?或者我可以说“这是在对象的基础部分设置的”或类似的话?
  • @user2672807 正如 [intro.object]/2 中的引文所说,子对象也是对象,因此在 @ 之内 / 之内调用 Bar 基类子对象并没有错987654343@ b基类对象(Bar只有一个基类)。但对我来说,后者听起来有点奇怪,可能会导致混淆;前缀 sub 强调所引用的对象不是完整的对象。 对象的基类部分 也应该没问题。对于一般的 OO,有 LSP,但这并不要求 superclass 有一个不同的 subobject
  • @user2672807 我试图避免使用类名 BaseDerived 并让自己感到困惑;)你是对的,它应该是 Foo 内的基类子对象/b.
【解决方案2】:

当通用的面向对象术语与 C++ 相关术语混合时,就会发生这种情况。

  • 子对象:存储在另一个对象中的任何对象(数组元素、基类对象和数据成员对象)。
  • 子类:一个通用的面向对象术语,指的是 C++ 中称为“派生类”的东西
  • 超类:一个通用的面向对象术语,指的是 C++ 中称为“基类”的东西。
  • 完整对象:未存储在另一个对象中的任何对象。

只是一点提示 - 在 C++ 领域中交谈时,我尝试使用 C++ 术语。在 Java 领域交谈时,我尝试使用 Java 术语。

【讨论】:

    【解决方案3】:

    Subobject 是 C++ 术语,表示一个对象是另一个对象的一部分;成员或基类。

    子类 是在其他语言中使用的术语,以及对继承的更一般讨论,表示派生类。这来自于将类层次结构绘制为倒置树的惯例,根在顶部。 C++ 不使用这个术语,可能是因为您描述的潜在混淆。

    为避免在讨论 C++ 中的继承时产生混淆,请使用 basederived 类的标准术语。

    【讨论】:

      【解决方案4】:

      我认为子对象通常会混淆地指代子类对象的基类相关部分(例如一些 vtable 指针),尤其是在涉及多重继承的设置中。我建议避免使用该术语并坚持使用更成熟的术语(Super/Sub、Base/Derived)。

      【讨论】:

        【解决方案5】:

        也许我会称它为父对象?

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-08-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-10-19
          • 2021-05-25
          相关资源
          最近更新 更多