我的问题有点冗长。一旦你解决了整个问题,请回答它。
我已按如下方式实施钻石问题:
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()设置为非虚拟时,此错误不会弹出并且程序成功运行(显然是以非多态方式)。为什么?什么链接(基类中的虚函数)与IsocelesTriangle中的Draw()签名有关?
答案 0 :(得分:4)
我认为,如果你没有覆盖Draw
中的IsoscelesTriangle
(并且更改签名不再覆盖),那么你最终会得到2 Draw
个函数。最终课程IsoscelesTriangle
,一个来自IsoscelesPolygon
,另一个来自Triangle
,并且都试图覆盖Draw
中的Polygon
。编译器发现它不明确。请注意,g ++会出现更易读的错误:
error: virtual function 'Polygon::Draw' has more than one final overrider in 'IsoscelesTriangle'
虚拟继承只是确保基础对象Polygon
在IsoscelesTriangle
中没有出现两次。在您的情况下,无论何时显式覆盖Draw
,编译器都会隐藏来自Draw
和Triangle
的其他2 IsoscelesPolygon
,因此不会产生混淆。
PS:即使您从Draw
完全删除IsoscelesTriangle
,也会发现相同的错误。无论如何,好问题,希望我做对了。
现在,关于问题的最后部分
当我将Polygon中的Draw()视为非虚拟
时,此错误不会弹出并且程序成功运行(显然是非多态的)
这里的想法是,现在每个Triangle
和IoscelesPolygon
都将Draw
声明为virtual
,所以基本上它们以干净状态开始并重载函数{{1}来自Draw
(标记为非虚拟)。然后,您最终会在Polygon
中找到2个不同的 Draw
函数,这些函数不会尝试覆盖 IsoscelesTriangle
Draw
}}