I'm using ptr_vector to store "shapes". I'm trying to fill it with derived shape classes, such as "circles", and every time I try to downcast them I get bad cast.
class Shape
{
public:
virtual ~Shape() {};
virtual void print() { std::cout << "shape" << std::endl; };
};
class Circle :
public Shape
{
public:
void print() { std::cout << "circle" << std::endl; };
};
int main()
{
boost::ptr_vector<Shape> shapes;
shapes.push_back(new Circle);
BOOST_FOREACH(Shape shape, shapes)
{
Circle& tempCircle = dynamic_cast<Circle&>(shape);
if(&tempCircle != NULL)
tempCircle.print();
}
system("PAUSE");
}
The problem is that your shape
is an object whose type is Shape
, and not a reference to an object whose (dynamic) type is Circle
.
Polymorphism only works with references or pointers. When treating objects as values and copy-construct or move-construct objects of a base class from objects of a derived class, what you get is slicing (definitely not something you want).
Try this instead:
BOOST_FOREACH(Shape& shape, shapes)
// ^
It would also make sense to use a reference to const
, probably - since you are not going to modify the referenced object inside the loop, so:
BOOST_FOREACH(Shape const& shape, shapes)
// ^^^^^^
{
Circle const& tempCircle = dynamic_cast<Circle const&>(shape);
// ^^^^^^ ^^^^^^
// ...
}
Also notice, that C++11 has range-based for
loops, which make BOOST_FOREACH
kind of obsolete. So if C++11 is an option, you could write:
for (auto const& shape : shapes)
{
Circle const& tempCircle = dynamic_cast<Circle const&>(shape);
// ^^^^^^ ^^^^^^
// ...
}
This said, it makes sense to point out (as Chad does in the comments) that you do not need to perform a dynamic downcast here, since print()
is a virtual function. When doing:
shape.print();
The function call will be dispatched to Circle::print()
if the object referenced by Shape
is an instance of Circle
.