问题描述
我的问题有点长。
我已经实现了钻石问题,如下所示:
I have implemented the Diamond Problem as follows:
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)时,它开始给我这样的错误:
It works perfectly fine and resolves the Diamond Problem due to virtual inheritance. But when I change Draw() in IsocelesTriangle to Draw(int), it starts giving me error like this:
此错误不会弹出并成功编译运行(非多态的方式)当我使Draw()在多边形作为非虚拟。为什么?什么链接它(基类中的虚函数)与IsocelesTriangle中的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. Why? What link it (virtual function in base class) has to do with the signature of Draw() in IsocelesTriangle?
推荐答案
这个想法是,如果你不覆盖 IsoscelesTriangle 中的 Draw (并且更改签名不会覆盖)你最终得到 IsoscelesTriangle 中的2 Draw 个函数,一个来自 IsoscelesPolygon 和三角形,并尝试从中覆盖 Draw 多边形。编译器发现它不明确。注意,g ++会产生一个更易读的错误:
I believe the idea is that if you don't override Draw in IsoscelesTriangle (and changing the signature is not overriding anymore), you end up with 2 Draw functions in the final class IsoscelesTriangle, one from IsoscelesPolygon and other from Triangle, and both try to override the Draw from Polygon. The compiler finds it ambiguous. Note that g++ spits out a more readable error:
error: virtual function 'Polygon::Draw' has more than one final overrider in 'IsoscelesTriangle'
虚拟继承只是确保基础对象 Polygon 在 IsoscelesTriangle 中不会出现两次。在你的情况下,每当你显式地覆盖 Draw ,编译器隐藏来自<$ c $的其他2 Draw c> Triangle 和 IsoscelesPolygon ,所以没有更多的混乱。
The virtual inheritance just ensures that the base object Polygon is not appearing twice in IsoscelesTriangle. In your case, whenever you explicitly override Draw, the compiler hides the other 2 Draws coming from Triangle and IsoscelesPolygon, so no more confusion.
PS:即使从中完全移除 Draw IsoscelesTriangle 。
PS: you'll find the same error even if you remove Draw completely from IsoscelesTriangle. Good question anyway, hope I got it right.
现在,对于问题的最后一部分
Now, regarding the last part of your question
这里的想法是,现在每个三角和 IoscelesPolygon 声明绘制为 virtual ,因此基本上他们从一个干净的状态开始,重载从多边形(标记为非虚拟)。然后,您最终会在 IsoscelesTriangle 中创建2个不同 绘制函数覆盖 绘制从多边形。
The idea here is that now each Triangle and IoscelesPolygon declare Draw as virtual, so basically they start with a clean state and overload the function Draw from Polygon (which was marked as non-virtual). You then end up with 2 different Draw functions in IsoscelesTriangle, which are not trying to override the Draw from Polygon.
这篇关于虚拟继承中的重载虚函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!