I've provided an extremely simplified version of the code which reproduces the error.
class Shape {
public:
virtual void func()=0;
};
class Circle : public Shape {
public:
Circle() { }
void func() { }
};
class Square : public Shape {
public:
Square() { }
void func() { }
};
int main() {
Circle c;
std::vector<Circle> circs;
std::vector<Shape*> shapes;
shapes.push_back(&c);
circs.push_back(shapes[0]); //ie, the Circle object that was just pushed into the 'shapes' vector.
}
I know that as of right now, this is functionally useless, and that I could just push the Circle object to the vector - however, in keeping with the shape analogy, my project also has triangles, squares, etc. I process data using a function which accepts Shape&
as a parameter, so that I can send all shapes to one function, instead of separate functions for each shape. That's besides the point, but gives insight into why I'm doing what I'm doing in the simplified code.
The last line in this code will not work. Could anyone tell me why? Or provide me with a solution/work-around? Is this considered bad programming-style?
EDIT: So I've solved the Object Slicing issue I was having. For anyone with the same issue, look at fgp's answer in the following thread:
I used the following to help allow what I was trying to do (Move a Circle
object to a Shape*
, compute some things, then push the Circle (which is in the Shape*
vector), to its final resting place, a Circle
vector:
class Shape {
public:
virtual Shape& operator=(const Shape& s) {
assign(s);
return *this;
}
virtual std::string getName() = 0;
virtual int getEdges() = 0;
protected:
std::string name;
int edges;
void assign(const Shape& s) {
this->name = s.name;
this->edges = s.edges;
}
};
class Circle : public Shape {
private:
int radius;
public:
Circle() { name = "Circle"; edges = 1; }
Circle(int rad) { name = "Circle"; edges = 1; radius = rad; }
virtual Circle& operator=(const Shape& s) {
if (const Circle* c = dynamic_cast<const Circle*>(&s))
assign(*c);
else{
std::cout << "BAD ASSIGNMENT IN CIRCLE.";
//THROW ERROR HERE INSTEAD OF THE ABOVE COUT
}
return *this;
}
std::string getName() { return name; }
int getEdges() { return edges; }
int getRadius() { return radius; }
void setRadius(int r) { radius = r; }
protected:
void assign(const Circle& c) {
Shape::assign(c);
this->radius = c.radius;
}
};
int main() {
std::vector<Shape*> shapes;
std::vector<Circle> circs;
Circle c2(5); //Creates a circle with 5 for the radius.
shapes.push_back(&c2); //Pushing the 5-radius circle into the Shapes* vector
Circle c3; //Creates a circle with default constructor (which does NOT define radius)
c3 = *shapes[0]; //Now, the overloaded assignment operator. Look at Circle::assign(const Shape&) function
circs.push_back(c3); //We push our newly assigned circle to our Circle vector
std::cout << "c3 radius: " << circs[0].getRadius(); //This will be 5!
}
It was a pleasant surprise to see this work! c3
will now know about c2
's radius, showing that the overloaded assignment operators work for a Shape
->Circle
conversion.
If anyone has some suggestions, please let me know!
(I will be creating a Circle
constructor that takes a (const Shape&) param, so I can use Circle c = *shapes[0]
, instead of having to separate the lines since it cannot find a constructor that accepts that parameter).
EDIT2: Also, if you use this, make sure you throw
an error (I left a comment where you should).