I have a base class Shape, and a derived class Circle which inherits Shape publically:
class Circle : public Shape
I made a C++ vector of Shape pointers, and I assigned Circle pointers to them. I'd read up a lot on object slicing so expected the code to treat the Circle in the vector as a Circle, not a Shape.
Can anyone point out what's wrong with this, given the output?
int main(void) {
vector<Shape*> shapes;
Circle* ncl = new Circle(-8, -8, 0.2f);
shapes.push_back(ncl);
cout << "Expected: " << *ncl << endl;
cout << "Reality: " << *shapes[0] << endl;
}
outputs:
Expected: Circle is at: -8,-8 and has a radius of: 0.2
Reality: Shape centered at point: -8,-8
I have overridden the << operator for both classes out of scope, so I think that's not the problem, but still - here's the code context of my overrides:
inline std::ostream& operator<< (std::ostream& stream, const Shape& shape) {
std::cout << "Shape centered at point: " << shape.getX() << "," << shape.getY();
return stream;
}
inline std::ostream& operator<< (std::ostream& stream, const Circle& circle) {
std::cout << "Circle is at: " << circle.getX() << "," << circle.getY() <<
" and has a radius of: " << circle.getR();
return stream;
}
All in all - I want to be able to access my Circle variables properly while they're stored in the Shape vector (with pointers or otherwise).
There's no slicing involved, it just looks like it.
Overloads are selected at compile time, from the static type as it is known to the compiler.
Since shapes
is a vector<Shape*>
, *shapes[0]
is a Shape&
, and that overload is chosen.
The common solution is to only write an operator<<
for the base class, and that in turn calls a virtual function on the object.
This will let the dynamic function dispatch select the function at runtime.
For instance:
struct Shape { virtual ostream& print(ostream& os) const { ... } };
struct Circle { ostream& print(ostream& os) const override { ... } };
ostream& operator<<(ostream& os, const Shape& s) { return s.print(os); }