虚继承中的重载虚函数
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 与 IsocelesTriangle
中 Draw()
的签名有什么关系(virtual
基 class 中的函数)?
我认为这个想法是,如果您不在 IsoscelesTriangle
中覆盖 Draw
(并且更改签名不再覆盖),您最终会得到 2 个 Draw
函数在最后的 class IsoscelesTriangle
中,一个来自 IsoscelesPolygon
,另一个来自 Triangle
,两者都试图覆盖 Polygon
的 Draw
。编译器发现它有歧义。请注意,g++ 吐出一个更具可读性的错误:
error: virtual function 'Polygon::Draw' has more than one final overrider in 'IsoscelesTriangle'
虚拟继承只是确保基础对象Polygon
不会在IsoscelesTriangle
中出现两次。在您的情况下,无论何时您显式覆盖 Draw
,编译器都会隐藏来自 Triangle
和 IsoscelesPolygon
的其他 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
这里的想法是现在每个 Triangle
和 IoscelesPolygon
都将 Draw
声明为 virtual
,所以基本上它们从一个干净的状态开始并重载函数 Draw
来自 Polygon
(被标记为非虚拟)。然后你在 IsoscelesTriangle
中得到 2 different Draw
函数,它们并没有试图 override Draw
来自 Polygon
.
我的问题有点冗长。请在您完成整个问题后才回答。
我已经实现了钻石问题如下:
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 与 IsocelesTriangle
中 Draw()
的签名有什么关系(virtual
基 class 中的函数)?
我认为这个想法是,如果您不在 IsoscelesTriangle
中覆盖 Draw
(并且更改签名不再覆盖),您最终会得到 2 个 Draw
函数在最后的 class IsoscelesTriangle
中,一个来自 IsoscelesPolygon
,另一个来自 Triangle
,两者都试图覆盖 Polygon
的 Draw
。编译器发现它有歧义。请注意,g++ 吐出一个更具可读性的错误:
error: virtual function 'Polygon::Draw' has more than one final overrider in 'IsoscelesTriangle'
虚拟继承只是确保基础对象Polygon
不会在IsoscelesTriangle
中出现两次。在您的情况下,无论何时您显式覆盖 Draw
,编译器都会隐藏来自 Triangle
和 IsoscelesPolygon
的其他 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
这里的想法是现在每个 Triangle
和 IoscelesPolygon
都将 Draw
声明为 virtual
,所以基本上它们从一个干净的状态开始并重载函数 Draw
来自 Polygon
(被标记为非虚拟)。然后你在 IsoscelesTriangle
中得到 2 different Draw
函数,它们并没有试图 override Draw
来自 Polygon
.