钻石多重继承 C++ 的问题,其中未正确分配新值

Issue with Diamond Multiple Inheritance C++ where new values are not being allocated correctly

提问人:shamalamadingdong 提问时间:11/3/2023 更新时间:11/3/2023 访问量:51

问:

我有以下钻石级继承:

       ClapTrap
      /         \
  ScavTrap    FragTrap
     \          /
      DiamondTrap

我将在下面分享我的类,但最终我尝试将 DiamondTrap 的成员变量设置为特定值,有些继承自 ScavTrap,有些继承自 FragTrap。 出于某种原因,即使我专门覆盖了这些值,它似乎仍保留了签名中最后一个继承类的值。

有人可以澄清以下几点:

  1. 在本练习中,我是否正确地实现了继承?
  2. 为什么当我尝试直接在 DiamondTrap 中设置和打印 ScavTrap::_energyPoints 时,它会设置并打印 FragTrap _energyPoints值?我检查了它肯定分配了 FragTrap::_energyPoints 而不是 ScavTrap::_energyPoints
 class ClapTrap {
protected:
    std::string _name;
    int         _hitPoints;  // constructor sets to 10
    int         _energyPoints; // constructor sets to 10
    int         _attackDamage; // // constructor sets to 0
    ClapTrap(void);

public:
    ClapTrap(const std::string name);
    ClapTrap(const ClapTrap& toCopy);
    ClapTrap& operator=(const ClapTrap& src);
    ~ClapTrap(void);

    void attack(const std::string& target);
    void takeDamage(unsigned int amount);
    void beRepaired(unsigned int amount);

    const std::string   getName(void) const;
    int                 getHitPoints(void) const;
    int                 getEnergyPoints(void) const;
    int                 getAttackDamage(void) const;

    void    setName(std::string name) ;
    void    setHitPoints(int hp) ;
    void    setEnergyPoints(int ep) ;
    void    setAttackDamage(int ad) ;
};

class FragTrap : virtual public ClapTrap {
// constructor sets inherited hitPoints = 100,
// energyPoints = 100 , attackDamage = 30
public:
    FragTrap(const std::string name);
    FragTrap(const FragTrap& toCopy);
    FragTrap& operator=(const FragTrap& src);
    ~FragTrap(void);

    void    highFiveGuys() const;

};

class ScavTrap : virtual public ClapTrap {
// constructor sets inherited hitPoints = 10,
// energyPoints = 50 , attackDamage = 20

public:
    ScavTrap(const std::string name);
    ScavTrap(const ScavTrap& toCopy);
    ScavTrap& operator=(const ScavTrap& src);
    ~ScavTrap(void);

    void    guardGate() const;

};

class DiamondTrap : public ScavTrap, public FragTrap {
private:
    std::string _name;
public:
    DiamondTrap(const std::string name);
    // DiamondTrap(const DiamondTrap& toCopy);
    // DiamondTrap& operator=(const DiamondTrap& src);
    ~DiamondTrap(void);
};
DiamondTrap::DiamondTrap(const std::string name) : ClapTrap(name + "_clap_name"),  ScavTrap(name), FragTrap(name){
    std::cout << "DiamondTrap constructor called" << std::endl;
    this->_name = ClapTrap::_name;
    this->_hitPoints = FragTrap::_hitPoints;
    this->_energyPoints = ScavTrap::_energyPoints;
    this->_attackDamage = FragTrap::_attackDamage;
    std::cout << this->getHitPoints() << std::endl; // output 100
    std::cout << this->getEnergyPoints() << std::endl; // output 100 should be 50
    std::cout << this->getAttackDamage() << std::endl; // output 30
    std::cout << this->_hitPoints << std::endl; // output 100
    std::cout << this->_energyPoints << std::endl; // output 100 should be 50
    std::cout << this->_attackDamage << std::endl; // output 30
    std::cout << ScavTrap::_energyPoints << std::endl; // output 100 should be 50
} 

谢谢

C++ 继承菱 形问题

评论

2赞 Pete Becker 11/3/2023
这并不能解决问题,但此代码中的任何内容都不需要额外的内容。 结束一行。此外,所有这些只是噪音。std::endl'\n'this->
1赞 BoP 11/3/2023
虚拟基类构造函数始终仅从最派生的类调用。
0赞 Pete Becker 11/3/2023
this->_energyPoints = ScavTrap::_energyPoints;将 的值设置为 的值。所示代码中没有任何内容初始化 的值(注释不会初始化值),因此没有理由期望它具有任何合理的值。_energyPoints_energyPoints_energyPoints
2赞 Pete Becker 11/3/2023
您可以剥离几乎所有这些代码,添加缺少的基本成员函数,并使用比当前问题中的内容少得多的代码来显示问题。
0赞 Pepijn Kramer 11/3/2023
钻石继承通常是一个设计缺陷,只是获得“代码重用”的一种方式。在这种情况下,使用一个纯抽象陷阱类(interfce)并单独派生所有实现可能更实用。或者查看 CRTP/mixin 模式,以在类之间重用部分实现。

答: 暂无答案