c++ - geeksforgeeks - Vector iterator no referenciable
vector c++ example (3)
Tengo una clase base abstracta llamada Shape de la cual se derivan tanto Circle como Rectangle, pero cuando ejecuto el siguiente código en VS 2005 obtengo el error. La aserción de Debug falló. Al mismo tiempo, no he sobrecargado el operador == en ninguna clase
Expresión: Vector iterator no se puede referenciar, ¿cuál es el motivo de esto?
vector<Shape*> s1;
s1.push_back(new Circle(point(1,2),3));
s1.push_back(new Circle(point(4,3),5));
s1.push_back(new Rectangle(point(1,1),4,5));
vector<Shape*> s2(s1);
reverse(s1.begin(),s1.end());
(*find(s1.begin(),s1.end(),new Circle(point(1,2),3)))->move(point(10,20));
Esta es una buena razón para usar boost :: ptr_vector.
No solo maneja el hecho de que tus objetos necesitan ser destruidos.
xtofl @: Olvidaste el destructor virtual.
Pero también hace que los miembros se vean como objetos al devolver referencias en lugar de punteros. Esto le permite utilizar los algoritmos estándar de forma mucho más natural en lugar de jugar con punteros en su función ''igual'' (que es muy similar a C ++).
#include <boost/ptr_container/ptr_vector.hpp>
#include <iostream>
class Shape
{
public:
~Shape() {}
bool operator==(Shape const& rhs) const
{
if (typeid(*this) != typeid(rhs))
{
return false;
}
return this->isEqual(rhs);
}
private:
virtual bool isEqual(Shape const& rhs) const = 0;
};
class Circle: public Shape
{
public:
Circle(int r)
:radius(r)
{}
private:
virtual bool isEqual(Shape const& r) const
{
Circle const& rhs = dynamic_cast<Circle const&>(r);
return radius == rhs.radius;
}
int radius;
};
class Rectangle: public Shape
{
public:
Rectangle(int h,int w)
:height(h)
,width(w)
{}
private:
virtual bool isEqual(Shape const& r) const
{
Rectangle const& rhs = dynamic_cast<Rectangle const&>(r);
return (height == rhs.height) && (width == rhs.width);
}
int height;
int width;
};
int main()
{
boost::ptr_vector<Shape> data;
data.push_back(new Circle(5));
data.push_back(new Circle(6));
data.push_back(new Rectangle(7,4));
boost::ptr_vector<Shape>::iterator f;
f = find(data.begin(),data.end(),Circle(6));
std::cout << "Find(" << (f - data.begin() ) << ")" << std::endl;
}
Like @David Pierre sugiere: find está basado en valores: se ve en el rango de iteradores para un puntero (por ejemplo, 0x0F234420) que es igual al puntero al new Circle(point(1,2),3)
que acaba de crear. Como es un objeto nuevo, no estará allí.
Puede find_if
esto utilizando find_if
con un operador que compare los objetos a los que hace referencia el puntero.
Sin embargo, el Criterium debería ser capaz de diferenciar entre tipos de formas.
class Shape {
public:
//amongst other functions
virtual bool equal( const Shape* ) const = 0;
};
class Circle : public Shape {
public:
bool equal( const Shape* pOther ) const {
const Circle* pOtherCircle = dynamic_cast<const Circle*>( pOther );
if( pOtherCircle == NULL ) return false;
// compare circle members
}
};
class Rectangle : public Shape {
public:
bool equal( const Shape* pOther ) const {
const Rectangle* pOtherR = dynamic_cast<const Rectangle*>( pOther );
if( pOtherR == NULL ) return false;
// compare rectangle members
}
};
Shape* pFindThis = new Circle(point(1,2),3);
vector<Shape*>::const_iterator itFound = find_if(s1.begin(),s1.end(),
bind1st( mem_fun( &Shape::equal ), pFindThis) ) );
delete pFindThis; //leak resolved by Mark Ransom - tx!
if( itFound != s1.end() ) {
(*itFound)->move(point(10,20));
}
Sencillo :
- falla el hallazgo ya que su Círculo recién creado no se puede encontrar en el vector con la comparación de Forma *
- un hallazgo fallido devuelve el iterador final que no es deferencable como capturado por una aserción de depuración
Para que funcione como lo desea, necesita comparar Shape, not Shape *
Como se señaló en otras respuestas, boost :: ptr_vector es una forma fácil de lograr esto.