虚继承中的重载虚函数

Overloaded Virtual Function in Virtual Inheritance

我的问题有点冗长。请在您完成整个问题后才回答。

我已经实现了钻石问题如下:

class Polygon
{

protected:
    int sides;

public:

    Polygon()
    {
        cout << "Polygon's Default Constructor being called." << endl;
    }

    Polygon(int a)
    {
        cout << "Polygon's parameterized Constructor being called." << endl;
        sides = a;
    }

    void virtual Draw()
    {
        cout << "Polygon being drawn." << endl;
    }

    virtual ~Polygon()
    {
        cout << "Polygon's Destructor being called." << endl;
    }

};


class Triangle : virtual public Polygon
{
    int Angles[3];
public:
    Triangle()
    {
        cout << "Triangle's Default Constructor being called." << endl;

    }

    Triangle(int a)
    {
        cout << "Triangle's parameterized Constructor being called." << endl;
        sides = a;
    }

    Triangle(int a, int b) : Polygon(a)
    {
        cout << "Triangle's double parameterized Constructor being called." << endl;
        //sides = a;
    }


    void virtual Draw()
    {
        cout << "Triangle being drawn." << endl;
    }

    ~Triangle()
    {
        cout << "Triangle's Destructor being called." << endl;
    }

};

class IsoscelesPolygon : virtual public Polygon
{
    void virtual Draw()
    {
        cout << "Isosceles Polygon's Draw Called." << endl;
    }
};

class IsoscelesTriangle : public Triangle, public IsoscelesPolygon
{

    void Draw(int )
    {
        cout << "Isoceles Triangle's Draw() Called." << endl;
    }
};

它工作得很好并且解决了由于虚拟继承导致的钻石问题。但是当我将 IsocelesTriangle 中的 Draw() 更改为 Draw(int) 时,它开始给我这样的错误:

当我将 Polygon 中的 Draw() 设置为非虚拟时,此错误不会弹出并且程序成功运行(显然以非多态方式)。为什么? link 与 IsocelesTriangleDraw() 的签名有什么关系(virtual 基 class 中的函数)?

我认为这个想法是,如果您不在 IsoscelesTriangle 中覆盖 Draw(并且更改签名不再覆盖),您最终会得到 2 个 Draw 函数在最后的 class IsoscelesTriangle 中,一个来自 IsoscelesPolygon,另一个来自 Triangle,两者都试图覆盖 PolygonDraw。编译器发现它有歧义。请注意,g++ 吐出一个更具可读性的错误:

error: virtual function 'Polygon::Draw' has more than one final overrider in 'IsoscelesTriangle'

虚拟继承只是确保基础对象Polygon不会在IsoscelesTriangle中出现两次。在您的情况下,无论何时您显式覆盖 Draw,编译器都会隐藏来自 TriangleIsoscelesPolygon 的其他 2 个 Draw,因此不会再造成混淆。

PS:即使从 IsoscelesTriangle 中完全删除 Draw,您也会发现同样的错误。好问题,希望我答对了。


现在,关于你问题的最后一部分

This error doesn't pop up and program successfully runs (in non-polymorphic way obviously) when I make the Draw() in Polygon as non-virtual

这里的想法是现在每个 TriangleIoscelesPolygon 都将 Draw 声明为 virtual,所以基本上它们从一个干净的状态开始并重载函数 Draw 来自 Polygon(被标记为非虚拟)。然后你在 IsoscelesTriangle 中得到 2 different Draw 函数,它们并没有试图 override Draw 来自 Polygon.