【问题标题】:What is the size of a class when it is inherited from a class which has all its members private in c++?当一个类从一个所有成员都在 C++ 中私有的类继承时,它的大小是多少?
【发布时间】:2013-08-01 17:40:26
【问题描述】:

假设有两个类 Base 和 Derived

class Base
{
  private: 
int a;
}
class Derived:public Base
{
private:
int b;
 }
 int main()
{
 Derived d;
 cout<<sizeof(d);
  }

输出是8。现在我的问题是当基类的成员变量是私有的并且派生类不能继承它时,为什么它在显示类的大小时包含数据成员?

【问题讨论】:

  • 说白了,因为DerivedBase。访问说明符只是控制谁和在哪里可以访问某些东西。
  • @jrok:实际上,is-a 关系不适用于私有继承。
  • @abarnert 实际上,就类布局而言(这是这里的全部主题),它确实成立。不可能有任何其他方式,否则地狱就会崩溃。
  • @abarnert 好的,是的。然后反过来:Derived has 总是有一个 Base。如果它在它之上公开继承,它也一个Base。
  • @syam:不,这仅适用于标准布局类。如果基类和派生类都有成员,那么所有的地狱都可以被打破,只要编译器能够正确地跟踪和解释这个地狱。

标签: c++ class inheritance layout


【解决方案1】:

私有成员仍然存在,无论它们是否可以从外部访问 - 如果您实际上不需要这些成员,请不要将它们放在那里。

Private 并不意味着“如果不使用就删除它”——它只是意味着“你不能在课堂外使用它”。通常,类中会有一些功能可以在真实类中使用ab - 但由于这是一个最小化的示例,直到它不再是有用的示例,所以你没有那个。

当一个类从另一个类继承(私有)成员变量时,它们是新类的一部分。如果它们是私有的,这只是意味着派生类不能直接使用它们 - 再次,在一个没有被最小化的真实类中,它会有一个函数可以在 Base 类中使用 a,并且一些函数在Derived 使用 b

【讨论】:

    【解决方案2】:

    如果您的基类中有非私有方法,它们可以访问和更改私有成员,因此这些成员仍然存在,因为任何子类都可以调用非私有方法。

    private 表示私有,不是不包括。

    为什么在没有方法的类中有私有成员?

    【讨论】:

      【解决方案3】:

      当您继承一个类时,您的类内存布局是具有基类的所有内容,然后是您在新类中定义的所有内容。

      您可以认为从 A 继承的 B 类是 A 加上 B 类的新增内容。

      【讨论】:

        【解决方案4】:

        如果base没有任何方法来操作私有成员,那么派生仍然不能访问成员,但是例外是base的朋友成员。如果要在派生中访问,请使私有成员受保护而不是私有。确保派生保留作为公共继承基础。请记住,派生类继承了所有基类:包括私有成员,但是,如果没有在基类中操作的任何方法,私有成员 var 是无用的,除非构造函数对其进行了一些处理,这不是一个好习惯。

        【讨论】:

          【解决方案5】:

          这个问题实际上与继承无关。有一个类只有私有字段,没有方法,也没有朋友。实际上,这些字段永远无法访问。为什么它不与任何地方的空类一样对待,包括继承?大多数编译器优化掉空基类。

          我不知道标准是否允许,但如果我写了一个编译器,我不会优化这样的成员。谁知道呢,也许这个类需要与其他类的布局兼容,也许是用另一种语言编写的。不过,我会发出有关此类字段的警告。

          【讨论】:

            【解决方案6】:

            这里的实际答案比看起来要复杂一些。

            Derived 不是标准布局类,因为派生最多的类和至少一个基类都具有非静态成员。因此,布局完全依赖于实现。您无法预测关于其成员的偏移量或类的大小的任何事情。它可能相当于一个结构体,在a 之后直接有b,或在其中只有b 的结构体,或在69105 之后在b 之后有a 的结构体填充字节数。

            因此,允许编译器检测到您无法在您的代码中访问 Derived::a 的事实是一个红鲱鱼。

            在实践中,我不知道有任何编译器不会以通常的标准布局方式将 Derived 构建为等同于 b 跟在 a 之后的结构......但这只是因为它是实现编译器的最简单方法,而不是因为语言需要它。

            【讨论】:

              猜你喜欢
              • 2019-03-13
              • 2016-07-09
              • 2013-02-12
              • 2017-04-14
              • 2013-04-11
              • 2013-03-12
              • 1970-01-01
              • 2014-11-27
              • 2017-03-15
              相关资源
              最近更新 更多