为什么我继承的接口不使用基类的重写?

Why doesn't my inherited interface use my base class's override?

本文关键字:基类 重写 继承 接口 为什么      更新时间:2023-10-16

我有一个接口和多重继承的问题。我希望设计我的程序,这样一个更新调用处理各种对象,每个行为的"构建块"隐藏在一个单一的函数。

例如,我想在一个地方将一个生物从a点移动到B点,而不管它是否必须执行移动前/后动作。但是,我的多重继承方案失败了(下面是bug),这让我觉得我需要在某个地方复制代码。

显然我对这个不够了解!(但我正在努力学习)

Q1。为什么IPhysics::Move"看到"Creature::Move(),在CreatureAirborne类?

Q2。我是否完全忽略了接口和/或多重继承的正确用法?如果是这样,任何指导是感激的!

#include <deque>
#include <memory>
class IGameObject
{
public:
    virtual ~IGameObject() {}
    virtual void Update() = 0;
};
class IPhysics
{
public:
    virtual ~IPhysics() {}
    virtual void Move() = 0;
};
class IPhysicsFlight : public IPhysics
{
public:
    virtual ~IPhysicsFlight() {}
    virtual void Land() = 0;
    virtual void TakeOff() = 0;
};
class Creature : public IGameObject, IPhysics
{
protected:
    virtual void Move() {}
public:
    Creature() {}
    virtual ~Creature() {}
    virtual void Update() {}
};

class CreatureAirborne : public Creature, IPhysicsFlight
{
private:
    virtual void Land() {}
    virtual void TakeOff() {}
public:
    CreatureAirborne() {}
    virtual ~CreatureAirborne() {}
    virtual void Update();
};
void CreatureAirborne::Update()
{
    TakeOff();
    Creature::Move();
    Land();
}
int main()
{
    std::deque<std::shared_ptr<Creature>> creatures;
    std::shared_ptr<Creature> cow(new Creature);
    creatures.push_back(cow);
// The butterfly fails to compile with 'cannot instantiate; void IPhysics::Move(void) is abstract'
//  std::shared_ptr<CreatureAirborne> butterfly(new CreatureAirborne);
//  creatures.push_back(butterfly);
    for (auto i : creatures)
    {
        i->Update();
    }
}

这在某种程度上必须遵循您的层次结构,但从编译器的角度来看,它的计算是正确的。

你在任何地方都没有虚拟继承,所以CreatureAirborne从某一点上会有重复的基类。您将有两个IPhysics实例。移动,从那里是抽象的,在生物分支上实现,但在IPhysicsFlight上保持抽象。

您可以通过在某处使用虚拟继承来解决这种情况,或者通过在后代中实现Move(例如仅调用存在的父版本)。

我会用不同的眼光看问题

class CreatureAirborne : public IPhysicsFlight,Creature

当代码运行

new CreatureAirborne ()

编译器将尝试构建IPhysicsFlight基类和Creature基类,而IPhysics是两个基类的事实并不起任何作用,而不是令人困惑。就编译器而言,IPhysicsFlight是抽象的,CreatureAirborne没有实现Move

当你执行

时,钻石问题实际上会发挥作用。
(new CreatureAirborne ())->Move()