为什么派生类的大小包括基类的私有成员?

sri*_*enu 6 c++ inheritance

我有以下代码:

class A {
  private:
    int i;
 };

class B : public A {
 private:
  int j;
 };
Run Code Online (Sandbox Code Playgroud)

当我检查时sizeof(B),似乎是sizeof(base) + sizeof(derived).但是,我对继承的理解是private基类的成员不会被继承.那为什么他们被包括在结果中sizeof(B)呢?

Kar*_*ath 8

所有成员变量都是继承的.该private protected public修饰符只能改变谁拥有访问这些变量


In *_*ico 6

你误解了什么private.在您的代码段中,它只是阻止非成员和非朋友A访问i.它只是一个访问控制修饰符.即使没有(直接)访问它的实例,B也会有数据成员.AB

一个类比,表明这确实有意义:

class Human
{
protected:
    void UseCognitivePowers() { brain.Process(); }
private:
    Brain brain;
    // ...
};

class StackOverflowUserInSilico : public Human
{
private:
    void AnswerStackOverflowQuestion(int questionId)
    {
        // ...
        // magic occurs here
        // ...
        UseCognitivePowers();
    }
};
Run Code Online (Sandbox Code Playgroud)

即使brain在是私有Human类,StackOverflowUserInSilico将有一个Brain,因为StackOverflowUserInSilico从导出Human.这是必需的,否则UseCognitivePowers()即使StackOverflowUserInSilico从中继承该方法,该函数也将无法工作Human.

当然,子类是否Human真正利用UseCognitivePowers()Human班级提供给他们的方法是完全不同的事情.


Mat*_* M. 5

您可能误解sizeof或误解了C ++对象的布局(在内存中)。

出于性能原因(避免间接成本),编译器通常会使用Composition实现Derivation:

// A
+---+
| i |
+---+

// B
+---+---+
| A | j |
+---+---+
Run Code Online (Sandbox Code Playgroud)

请注意,如果private,即使包含,B也无法窥视A

然后,sizeof操作员将返回的大小B,包括必要的填充(用于对齐校正)(如果有)。

如果您想了解更多,我衷心推荐里面的C ++对象模型斯坦利A.李普曼。尽管依赖于编译器,但实际上许多编译器确实使用相同的基本原理。