【问题标题】:Why private members get inherited?为什么私有成员会被继承?
【发布时间】:2013-10-23 14:50:01
【问题描述】:

所以基类中的private 成员也在继承类中,但不能在其中访问,对吧?
它们实际上是否在分配给继承对象的内存中?

【问题讨论】:

  • 继承是is-a 关系,所以是的,基类需要的所有内存都需要在子类中。

标签: c++ inheritance access-modifiers


【解决方案1】:

它们实际上是否在分配给继承对象的内存中?

是的,它们需要存在。私有成员是基类实现细节的一部分。没有它们,一般来说,基类将无法运行(这就是它们最初存在的原因)。

将它们设为私有只允许基类根据自己的选择创建其实现,而不会将其暴露给任何人,包括子类。

【讨论】:

  • 除了这个好的答案之外,我想说的是,基本上当你有一个基类 MyBase 并且它被某个类 MyDerived 继承时(无论如何——公共、私有或受保护) ,当你创建一个 MyDerived 类型的对象时,在内存中的对象布局中,你实际上会有一个 MyBase 类型的对象。所以简单地说:每个 MyDerived 类型的对象内部都会有一个 MyBase 类型的对象。
  • @BlackCat - Re 简单地说:MyDerived 类型的每个对象内部都会有一个 MyBase 类型的对象。 Diamond 继承。假设 B 和 C 都从 A 虚拟继承,D 从 B 和 C 继承。嵌入在 D 类实例中的 B 和 C 对象中的至少一个不会在它们“内部”包含 A 对象。
  • @David:B 和 C 都有一个指向公共(共享)基类 A 对象的指针。虽然它们内部不一定有 A 类对象,但它们的行为就像它们一样。
【解决方案2】:

是的。例如,您可以使用基类中的公共函数来操作私有数据,即使在派生类的实例中也是如此:

class Base { 
    int x;
public:
    Base() : x(0) {}
    void inc() { ++x; }
    void show() { std::cout << x << "\n"; }
};

class Derived : public Base { 
};

int main() { 
    Derived d;
    d.show();
    d.inc();
    d.show();
}

使用正常运行的编译器,必须显示:

0
1

...表明 Base 对象中的数据存在于 Derived 对象中,即使它不是(直接)可访问的。

当然,对于 C++ 中的几乎任何东西,都有“as-if”规则——如果编译器可以确定它可以以某种方式为程序产生正确的可观察行为,即使不包括基类,那么它是免费的。最明显的例子是,如果您在基类中包含一些在实践中根本没有使用过的东西(成员函数或数据)。

【讨论】:

  • 如果你编译成一个可分发的 DLL,你怎么知道某个特定的成员函数没有被使用?
  • @TemplateRex:有可能它不能,所以在这种情况下,它很可能没有省略它的可能性。
  • 我认为一次派生类的根本问题是它可以被再次继承,并且潜在的孩子是一个开放集。因此,除非Derived 被标记为final,否则我认为编译器永远无法将as-if 规则应用于其类布局。最重要的是,未来调用者的集合也是一个开放集。
  • @TemplateRex:编译器(本身)可能无法做到——但链接器通常可以/将会。
【解决方案3】:

是的,他们是,

当派生类的对象被构​​造时,它的所有基类也首先被构造。

考虑这个例子:

class Base
{
 int x;

 public:
  Base(int px)
   : x(px)
  {
  }
};

class Derived : public Base
{
 int y;
public:
  Derived(int px, int py)
   : y(py), Base(px)
  {
  }
};

此示例编译并运行,并且在您到达 Derived 构造函数的主体之前初始化 Base(构造函数被调用)。

【讨论】:

    猜你喜欢
    • 2011-01-02
    • 2020-09-04
    • 2020-09-01
    • 2018-05-11
    • 1970-01-01
    • 2013-02-12
    • 2015-01-21
    • 2011-09-26
    • 2011-02-10
    相关资源
    最近更新 更多