从虚拟基类继承而没有创建菱形问题的正确的初始化程序列表

问题描述 投票:0回答:1

因此,当您在继承中创建菱形时,派生程度最高的类需要在其初始值设定项列表中显式调用虚拟类的子对象的构造函数。

但是从虚拟类继承的类又如何呢? 例如Bow继承自虚拟基类Weapon,Bow是否也需要在其初始值设定项列表中调用Object的构造函数,为什么?

我与所有的类继承和初始化器列表有些纠结,我只需要先清除所有内容,然后再继续并删除初始化器列表中的所有不必要的调用。

对象的构造函数使用sf :: Vector2f,它是两个浮点数。到目前为止,我已经将Movable,Weapon和Projectile用作虚拟基类,因为它们是钻石的一部分。

enter image description here

// sf::Vector2f is an SFML data type which consists of two floats

class Object
{
private:
    sf::Vector2f m_pos;
public:
    Object(sf::Vector2f start_pos) {m_pos = start_pos;};
}

class Movable : virtual public Object
{
public:
    Movable(sf::Vector2f start_pos) : Object(start_pos) { ... };
}

class Weapon : virtual public Object
{
public:
    Weapon(float shotDelay, bool isStealth) : Object(sf::Vector2f(0,0)) { ... };
}

class Projectile : public Movable
{
public:
    Projectile (sf::Vector2f startPos, int damage) : Movable(startPos) { ... };
}

class Bow : public Weapon
{
public:
    Bow() : Weapon(BOW_SHOT_DELAY, BOW_STEALTH) { ... };
}

class Grenade : public Weapon, public Projectile
{
public:
    Grenade() : Weapon(GRENADE_SHOT_DELAY, GRENADE_STEALTH) {};//for Weapon
    Grenade(sf::Vector2f startPos) : Projectile(startPos, GRENADE_DAMAGE);//for Projectile
}
c++ inheritance multiple-inheritance base-class virtual-inheritance
1个回答
0
投票

所以经过一些研究,有用的评论,反复整理我的代码后,我弄清楚了答案和出了什么问题。我正在为Object构造函数提供一个默认参数,因此无论我是否将该调用包含在类的初始化列表中,都以这种方式调用它。

从虚拟基类继承的类如果它们没有默认构造函数,则必须在其初始化程序列表中包括调用虚拟基类的子对象的构造函数

因此,在我的示例中,由于Bow继承自从Object继承的虚拟基类Weapon,因此其初始化列表将如下所示:

Bow::Bow() : Object(BOW_STARTING_POS), Weapon(BOW_SHOT_DELAY, BOW_STEALTH)
{
  //constructor code
}

为完整起见,我添加了没有默认构造函数时手榴弹初始化程序的列表:

Grenade::Grenade() : Object(GRENADE_STARTING_POS), Weapon(GRENADE_SHOT_DELAY, GRENADE_STEALTH)
{
  //weapon constructor code
}

Grenade::Grenade() : Object(GRENADE_STARTING_POS), Projectile(GRENADE_STARTING_POS, GRENADE_DAMAGE)
{
  // projectile constructor code
}

P.S。手榴弹被分为两个构造函数,因为我的设计需要这样做。在另一种情况下,对于从两个虚拟基类继承的类,您只需要一个构造函数,则一个初始化程序列表可以包含所有这样的构造函数调用:

Grenade::Grenade() : Object(GRENADE_STARTING_POS), Projectile(GRENADE_STARTING_POS, GRENADE_DAMAGE), Weapon(GRENADE_SHOT_DELAY, GRENADE_STEALTH)
{
  //constructor code
}
© www.soinside.com 2019 - 2024. All rights reserved.