【问题标题】:Accessing Base class from sub-sub-class or grandchild从子子类或孙子访问基类
【发布时间】:2018-01-30 22:24:45
【问题描述】:

我只想直截了当地说,因为当我学习继承时,我注意到我可以从已经派生的类继承,并且从最派生的类直接访问基类的成员。我认为以下内容表明了我的意思:

#include <iostream>

struct Base
{
    int member = 0;     // All members null
};

struct D1 : Base {};
struct D2 : Base {};
struct D3 : Base {};
struct D4 : Base {};

struct MostDerived : D1, D2, D3, D4 {};  // I know MostDerived now has 4 copies of Base


int main()
{
    MostDerived mostderived{};
    mostderived.D2::member = 2;                     // D2::Base::member = 2
    mostderived.D3::member = 3;                     // D3::Base::member = 3
    mostderived.D4::member = 4;                     // D4::Base::member = 4

    std::cout << mostderived.D1::member << '\n';        // Haven't touched D1, is still zero
    std::cout << mostderived.D1::Base::member << '\n';  // Equals 0, equivalent to above line
    std::cout << mostderived.Base::member << '\n';      // Read Base scope directly from most derived, equals zero

    mostderived.Base::member++;                         // Assign to member in Base scope directly from mostderived
                                                        // it now equals 1

    std::cout << mostderived.D1::member << '\n';        // But also does D1::member equal 1

    return 0;
}

所以通过mostderived.Base::member++ 我改变了mostderived.D1::member 的值。我只是想知道像这样访问Base 是否有意义,以及为什么它特别改变了D1 的成员副本。我描绘布局的方式是MostDerived 包含D1D2D3D4,每个都包含Base,所以它看起来像下面这样。

【问题讨论】:

  • 是的,我经常听到支持组合而不是继承,并且我的调试器实际上将派生类显示为“包含”基类,所以我认为继承与仅将基类弹出到派生类定义,当然它带有其他特性。
  • main.cpp:24:40: error: 'Base' is an ambiguous base of 'MostDerived' std::cout &lt;&lt; mostderived.D1::Base::member &lt;&lt; '\n'; 无法为我构建代码
  • @kim366 我明白了,这很有趣。我只在我的 Visual Studio 上试过,所以也许它应该是一个模棱两可的事情。虽然我会认为模棱两可的部分会是最衍生的。Base::member 部分
  • 看看这个对常规继承和虚拟继承的解释,它可能会澄清一点:) stackoverflow.com/a/2659142/7034621
  • @Zebrafish 将您的代码粘贴到此处:coliru.stacked-crooked.com 以查看 g++ 中的所有错误

标签: c++ class inheritance base-class


【解决方案1】:

所以通过执行 mostderived.Base::member++ 我改变了 mostderived.D1::member.

如果 'MostDerived' 继承自 D1-4,则

mostderived.Base::member++;
                  ^

模棱两可。

因为“MostDerived”具有这种层次结构

int Base::member
int Base::member
int Base::member
int Base::member

Base 可以替换为 D1-4 中的任何一个。


如果你会使用虚拟继承

struct D1 : virtual Base {};
struct D2 : virtual Base {};
struct D3 : virtual Base {};
struct D4 : virtual Base {};

这将导致“MostDerived”只包含 一个 基类,所以它不会再模棱两可了

mostderived.Base::member++;

并且可以通过所有 D1-4 访问这个member

mostderived.D1::member = 1;
mostderived.D4::member = 4;

当然,因为所有 D 共享相同的变量,所以它对所有人都有相同的值,例如:

MostDerived mostderived{};
mostderived.Base::member = 1;
std::cout << mostderived.D1::member << mostderived.D2::member << mostderived.D3::member << mostderived.D4::member;

将打印1111

【讨论】:

  • 正如 kim366 指出的那样,它不能在链接的在线编译器上编译。它是模棱两可的,这绝对是有道理的。我在 Visual Studio 上运行。
  • 您对此还有其他问题吗? :-)
  • 不,我现在明白这是一个模棱两可的表达式,可能是我的编译器中的一个错误。谢谢。
  • 我很快会在这个例子中用virtual继承来编辑我的答案,你可以看看。不客气。
猜你喜欢
  • 2013-01-16
  • 2018-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-05
  • 2011-09-05
  • 2017-03-01
  • 1970-01-01
相关资源
最近更新 更多