Home > Software design >  Template function ignores members from inherited class
Template function ignores members from inherited class

Time:12-17

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();
  • Related