I am trying to write a program that compares some Shapes by their area, Shape being the base class. The program has 2 other classes that are derived from the Shape class.
This is how I defined them:
class Shape
{
protected:
string color;
public:
Shape();
Shape(string);
virtual double Perimeter();
virtual void printMe();
virtual double Area();
};
class Square:
public Shape
{
int x, y;
double side;
public:
Square();
Square(string, int, int, double);
double Perimeter();
void printMe();
double Area();
};
class Circle:
public Shape
{
int x, y, radius;
public:
Circle();
Circle(string, int, int, int);
double Perimeter();
void printMe();
double Area();
};
In main, I created the following objects:
Shape f1, f2("green");
Circle c1, c2("green", 2, 2, 2);
Square p1, p2("blue", 0, 0, 5);
Shape* f3 = &c1;
Shape* f4 = &c2;
Shape* f5 = new Square("blue", 1, 0, 2);
Shape* f6 = &p2;
And I want to build a function that takes any Shape objects and return the one that has the maximum area. I tried like this:
template <typename T>
T maxim(initializer_list<T> list) {
T maxx;
for (auto i : list)
{
if (i.Area() > maxx.Area())
maxx = i;
}
return maxx;
}
In main, I tried to call the function:
maxim<Shape>({*f3, *f4, *f5, *f6}).printMe();
The program doesn't have any errors, only an empty string is displayed (due to the fact that maxx
is a Shape
that is initialized with an empty string).
The objects f3
,f4
,f5
and f6
are displayed right when I call the printMe()
method, so I figured that when I call the maxim
function, only the member color
is assigned to the objects. There is no x
,y
,side
or radius
member assigned to them.
I think the problem is that the objects are just Shapes
and they only have the color
member.
Is there any way the objects in the list can be interpreted as Cricles and Squares so I can compare them using Area()
method?
CodePudding user response:
You are trying to use polymorphism here. Unfortunately polymorphism in C works well with pointers or references but not with plain objects because of slicing (thank to @Jarod42 for that reference).
And as references cannot be assigned to (you instead assign to the ref-ed object) you cannot use them in containers nor in initializer lists.
That means that you will have to use good old pointers in maxim
:
template <typename T>
T* maxim(initializer_list<T*> list) {
T* maxx = nullptr;
for (auto i : list)
{
if (nullptr == maxx || i->Area() > maxx->Area())
maxx = i;
}
return maxx;
}
From there on, you will be able to do:
maxim<Shape>({f3, f4, f5, f6})->printMe();