My question is bit lengthy. Kindly answer it only once you go through the whole problem.
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;
}
};
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:
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 does it (virtual
function in base class) have to do with the signature of Draw()
in IsocelesTriangle
?
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'
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 Draw
s coming from Triangle
and IsoscelesPolygon
, so no more confusion.
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
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
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
.