【问题标题】:Overloaded Virtual Function in Virtual Inheritance虚继承中的重载虚函数
【发布时间】:2015-01-24 03:41:35
【问题描述】:

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

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

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;
    }
};

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

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

【问题讨论】:

    标签: c++ inheritance polymorphism overloading


    【解决方案1】:

    我相信这个想法是,如果你不在IsoscelesTriangle 中覆盖Draw(并且更改签名不再覆盖),你最终会在最终类IsoscelesTriangle 中得到2 个Draw 函数,一个来自IsoscelesPolygon,另一个来自Triangle,并且都试图覆盖PolygonDraw。编译器发现它模棱两可。请注意,g++ 会吐出一个更易读的错误:

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

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

    PS:即使你从IsoscelesTriangle 中完全删除Draw,你也会发现同样的错误。无论如何,这是个好问题,希望我做对了。


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

    当我将 Polygon 中的 Draw() 设置为非虚拟时,此错误不会弹出并且程序成功运行(显然以非多态方式)

    这里的想法是现在每个TriangleIoscelesPolygonDraw 声明为virtual,所以基本上它们从一个干净的状态开始并从Polygon 重载函数Draw(标记为非虚拟)。然后,您会在 IsoscelesTriangle 中得到 2 个不同 Draw 函数,它们不会试图覆盖 Polygon 中的 Draw

    【讨论】:

    • 你的意思是如果Draw() 不是虚拟的可能......仍在尝试解决这个问题
    • 是的,正如我在问题中提到的那样:当我将 Polygon 的 Draw() 转换为非虚拟时,不会弹出错误并且程序可以毫无问题地执行。
    • 但即使我将 Triangle 和 IsoscelesPolygon 中的 Draw() 转换为非虚拟,仍然会出现错误。唯一改变它的是 Polygon 的 Draw() 转换为非虚拟的。
    • 即使您没有将中间函数显式标记为virtual,该函数仍被视为virtual。因此,如果您有一个带有virtual void Base::f() 的基类,那么void Derived::f()自动 虚拟的,无需显式指定virtual 关键字。
    • 这对我来说是新事物。你的回答很好,但我仍然对我遇到的现象持怀疑态度
    猜你喜欢
    • 2020-03-01
    • 1970-01-01
    • 2015-09-25
    • 1970-01-01
    • 2013-07-24
    • 2019-07-24
    • 1970-01-01
    • 1970-01-01
    • 2014-07-28
    相关资源
    最近更新 更多