I am new to C++ and trying to make list polymorphic/accepting anything deriving from a base class. The issue is that this list must be private, using separate methods to append and interrogate it.
After some research, I was able to get close in a safe manner through smart pointers.
Here is what I have arrived at:
class Shape
{
public:
Shape(std::string name)
{
this->name = name;
}
std::string name;
std::string getName(void)
{
return this->name;
}
};
class ShapeCollector
{
public:
void addShape(Shape shape)
{
this->shapes.push_back(std::make_unique<Shape>("hey"));
}
private:
std::vector <std::unique_ptr<Shape>> shapes;
};
I would like to be able to replace the make_unique call with the shape parameter, however nothing I try seems to play correctly.
I could create each derived class inside ShapeCollector, mirroring the constructor arguments as parameters, but this feels very counter intuitive.
Any help would be appreciated!
Write addShape
to take the derived class as a template parameter:
template<class Derived, class... Args>
void addShape(Args&&... args) {
// std::forward will correctly choose when to copy or move
std::unique_ptr<Shape> shape (new Derived(std::forward<Args>(args)...));
shapes.push_back(std::move(shape));
}
This will allow you to give addShape
the arguments for the derived classs constructor. For example, if we have a
Circle` class:
class Circle : public Shape {
double radius;
double x;
double y;
public:
Circle(double radius, double x, double y)
: Shape("circle"), radius(radius), x(x), y(y)
{}
};
Adding it is simple:
ShapeCollector shapes;
shapes.addShape<Circle>(10.0, 0.0, 0.0);