有其他虚拟基类时如何避免对基类函数的模糊调用

Posted

技术标签:

【中文标题】有其他虚拟基类时如何避免对基类函数的模糊调用【英文标题】:How to avoid ambiguous call to base class function when have other virtual base classes 【发布时间】:2013-11-13 19:50:43 【问题描述】:

此代码不起作用。

class Collidable
   public:
   virtual Vec2 Pos()=0;
;

class Square
    Vec2 pos;
    public:
    Vec2 Pos()
        return pos;
    
;
class Box:public Square,public virtual Collidable

;
main()
    Box bla;
   cout<<bla.Pos()<<endl;

但如果我这样做,它会起作用。

class Box:public Square,public virtual Collidable
   public:
    Vec2 Pos()
        return Square::Pos();
    

我的问题是我有一个像 Square 这样的类,我有很多像 Pos() 这样的函数,我真的觉得我不应该这样说

    Vec2 Pos()
        return Square::Pos();
    

对于每一个函数一遍又一遍,当我认为这是从另一个类继承时的默认行为时。我怎样才能避免在这里输入大量多余的内容,以及调用 Pos() 有什么含糊之处,而它只有一个定义?

【问题讨论】:

【参考方案1】:

模棱两可的部分是由于您的类层次结构中有两个函数具有相同的函数名称但不同(即Square::PosCollidable::Pos 彼此没有关系)。您必须说明您在 Box 类中使用的函数。在不了解架构的其余部分的情况下,很难推荐解决方案,但我猜您在这里并不需要多重继承。您可能可以将其更改为:

class Collidable

public:
   virtual Vec2 Pos()=0;
;

class Square : public Collidable

    Vec2 pos;
public:
    virtual Vec2 Pos()
    
        return pos;
    
;

class Box : public Square


;

main()

    Box bla;
    cout<<bla.Pos()<<endl;

【讨论】:

抱歉,我应该解释一下,我引入 Collidable 接口的目的是让 Box 可碰撞,而 Square 不可碰撞。在您的示例中,正方形也可以碰撞,使其成为相同的东西。 你可以用一个简单的布尔标志来做到这一点。无需引入类层次结构来支持这一点。一般来说,当您看到自己对多个抽象基类(例如接口类)的集合使用多重继承时,您很可能可以用更简单的解决方案来解决相同的问题。正如我所解释的,您的代码中的问题是您有 2 个不同的虚拟方法,它们的名称相同,来自不同的基类。您必须指定要覆盖哪一个,或重命名其中一个。 虽然问题不同,但here 和here 的答案与您正在尝试做的事情相关。 但我并没有将多重继承用于抽象基类的集合。 Box 仅从一个父级继承,并实现一个接口。只有一个定义函数和一个纯虚函数。是的,我可以使用布尔标志,但是当您有许多不同的此类接口或不同类型时,我认为当我希望能够在编译时知道时,这将是很多额外的运行时检查。此外,它可以判断某物是否可碰撞,是否属于其类型。 这涉及到它的哲学部分有点太多了。可以这么说,如果不明确说明要使用哪个函数(通过using 指令或全范围调用),您将无法做您想做的事情。

以上是关于有其他虚拟基类时如何避免对基类函数的模糊调用的主要内容,如果未能解决你的问题,请参考以下文章

使用空基类的聚合初始化时如何避免

如何避免在基类初始化程序中调用默认构造函数?

虚基类在解决二义性中的问题中的作用是啥

通过基类的指针或引用调用虚函数构成多态

通过基类的指针或引用调用虚函数构成多态

继承和派生