BOOST и C ++: не могу заставить полиморфизм работать

Я использую ptr_vector для хранения «фигур». Я пытаюсь заполнить его производными классами фигур, такими как «круги», и каждый раз, когда я пытаюсь уменьшить их, я получаю плохой состав.

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");
}

2

Решение

Проблема в том, что ваш shape это объект, тип которого Shapeа не ссылка на объект, чей (динамический) тип Circle,

Полиморфизм работает только со ссылками или указателями. При обработке объектов как ценности и копировать-конструировать или перемещать-конструировать объекты базового класса из объектов производного класса, что вы получите нарезка (определенно не то, что вы хотите).

Попробуйте это вместо этого:

BOOST_FOREACH(Shape& shape, shapes)
//                 ^

Было бы также целесообразно использовать ссылку на const, вероятно — поскольку вы не собираетесь изменять ссылочный объект внутри цикла, поэтому:

BOOST_FOREACH(Shape const& shape, shapes)
//                  ^^^^^^
{
Circle const& tempCircle = dynamic_cast<Circle const&>(shape);
//     ^^^^^^                                  ^^^^^^

// ...
}

Также обратите внимание, что C ++ 11 имеет диапазон for петли, которые делают BOOST_FOREACH вид устарел. Так что, если C ++ 11 является опцией, вы можете написать:

for (auto const& shape : shapes)
{
Circle const& tempCircle = dynamic_cast<Circle const&>(shape);
//     ^^^^^^                                  ^^^^^^

// ...
}

При этом имеет смысл указать (как Чад в комментариях) что вам не нужно выполнять динамическое снижение, так как print() это виртуальная функция. При выполнении:

shape.print();

Вызов функции будет отправлен Circle::print() если объект, на который ссылается Shape это пример Circle,

6

Другие решения

Кроме того, вы не используете dynamic_cast правильно. Если вы динамически передаете ссылку, и объект на самом деле не принадлежит классу, к которому вы ее приводите, то бросок std::bad_cast, Он не возвращает ноль, потому что нет такой вещи, как ссылка с нулевым адресом. Итак, вот правильный путь:

Circle* tempCircle = dynamic_cast<Circle*>(&shape);
if(tempCircle != NULL)
tempCircle->print();

(Вы можете на самом деле иметь ссылку r с &r == NULL, но только после разыменования нулевого указателя, который имеет неопределенное поведение.)

0

По вопросам рекламы [email protected]