【问题标题】:Inheritance from parents with same members来自具有相同成员的父母的继承
【发布时间】:2021-11-01 03:05:26
【问题描述】:

我在访问多重继承下父母的成员(同名)时遇到问题。我有 4 个类(经典钻石问题)定义如下:

class ClapTrap
{
    public:
        ClapTrap(void)
        { _hitpoints = 0; }
        ~ClapTrap() { }

    protected:
        int             _hitpoints;
};

class ScravTrap : public virtual ClapTrap
{
    public:
        ScravTrap(void)
        { _hitpoints = 1; }
        ~ScravTrap() { }
};

class FragTrap : public virtual ClapTrap
{
    public:
        FragTrap(void)
        { _hitpoints = 2; }
        ~FragTrap() { }
};

class DiamondTrap : public ScravTrap, public FragTrap
{
    public:
        DiamondTrap(void)
        { 
            std::cout << ScravTrap::_hitpoints << std::endl;
            std::cout << FragTrap::_hitpoints << std::endl;
        }
        ~DiamondTrap() { }
};


int main()
{
    DiamondTrap d;
}

我的主要输出是

2
2

我希望这个输出是

1
2

因为我第一次打印 DiamondTrap 的 ScravTrap::_hitpoints 成员(并且 ScrapTrap::_hitpoints 被初始化为 1),而我第二次打印 DiamondTrap 的 FragTrap::_hitpoints 成员(之前已经初始化到 2)。我知道 DiamondTrap 继承了两个 _hitpoint 成员,但我怎样才能正确访问它们?

注意即使我在 DiamondTrap 类的公共部分的开头写了using ScravTrap::_hitpoints,输出仍然是一样的。为什么会这样?

编辑 一些答案提到虚拟继承只生成一个基类的副本。在创建 DiamondTrap 的实例时,我只想调用一次 ClapTrap 的构造函数。我怎样才能做到这一点并且还可以访问 ScravTrap::_hitpoints 和 FragTrap::_hitpoints?如果我在每个父类中有两个成员怎么办? DiamondTrap 可以从 FragTrap 继承其中一个,从 ScravTrap 继承其中之一吗?我该怎么做?

【问题讨论】:

  • virtual继承有什么作用?
  • ...这意味着...
  • @TedLyngmo:我很确定 StoryTeller-UnslanderMonica 知道答案 :-) 问题是针对 OP 的。改进了Rubber duck :-)
  • @TedLyngmo - 坡定律。每次:)
  • “我怎样才能做到这一点,同时还能访问ScravTrap::_hitpointsFragTrap::_hitpoints?” 要么你有虚拟继承,要么你有ScravTrap::_hitpointsFragTrap::_hitpoints是同一个变量,或者您使用非虚拟继承(“Y 继承”)拥有 2 个ClapTrap(因此每个构造函数调用,总共 2 个)。

标签: c++ inheritance multiple-inheritance


【解决方案1】:

只有 一个 ClapTrap,因为您使用 virtual 继承,并且只有一个 _hitpoints

你不能让那个_hitpoints 变量携带多个值。

首先,构造ClapTrap,分配0,然后构造ScravTrap,分配1,最后构造FragTrap,将2 分配给同一个_hitpoints 变量。

我想在创建DiamondTrap 的实例时只调用一次ClapTrap 的构造函数。

这就是你现在所做的。

我怎样才能做到这一点并同时访问ScravTrap::_hitpointsFragTrap::_hitpoints

你不能。您必须选择其中一个。

如果没有virtual 继承,您将有两个构造函数调用以及ScravTrap::_hitpointsFragTrap::_hitpoints

使用virtual 继承,您将有一个构造函数调用,而只有一个_hitpoints

【讨论】:

  • ... 它将携带构造函数上次运行时最后分配给它的值,它是基类列表中的最后一个,它分配了 2。
  • @Peter-ReinstateMonica 好点。我在答案中添加了构造模式。
  • 如果每个父类中有两个成员怎么办? DiamondTrap 可以从 FragTrap 继承其中一个,从 ScravTrap 继承其中之一吗?我该怎么做?
  • "每个父类有两个成员" - 总共四个成员变量?我没明白你的意思。
【解决方案2】:

我希望这个输出是

1
2

一个int对象不能同时有两个不同的值,所以这个输出是不可能的。

知道 DiamondTrap 继承了两个 _hitpoint 成员

只有一个ClapTrap,因此只有一个_hitpoint 成员。

为什么会这样?

发生这种情况是因为您使用了虚拟继承。 _hitpoints 首先在虚拟基 ClapTrap 的构造函数中初始化为不确定值,然后将其赋值为 0。之后,基 ScravTrap 的构造函数将其赋值为 1,最后,基 FragTrap 的构造函数将其分配给 2。

希望在创建 DiamondTrap 的实例时只调用一次 ClapTrap 的构造函数。我怎样才能做到这一点并且还可以访问 ScravTrap::_hitpoints 和 FragTrap::_hitpoints?

ClapTrap 中删除成员并将成员添加到ScravTrapFragTrap 将实现您想要的。不清楚你为什么想要这个。

【讨论】:

    猜你喜欢
    • 2021-10-31
    • 1970-01-01
    • 1970-01-01
    • 2011-02-07
    • 1970-01-01
    • 2020-10-21
    • 2016-02-15
    • 2017-07-02
    • 2020-12-14
    相关资源
    最近更新 更多