9 Stimmen

Vektor-Iterator nicht dereferencierbar

Ich habe eine abstrakte Basisklasse namens Shape, von der sowohl Circle als auch Rectangle abgeleitet sind, aber wenn ich den folgenden Code in VS 2005 ausführe, erhalte ich die Fehlermeldung Debug assertion failed. Gleichzeitig habe ich in keiner Klasse den Operator == überladen

Expression:Vector Iterator nicht dereferencable, was ist der Grund dafür.

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

12voto

David Pierre Punkte 9223

Einfach:

  • find schlägt fehl, da der neu erstellte Kreis nicht im Vektor mit dem Vergleich von Shape * gefunden werden kann.
  • eine fehlgeschlagene Suche gibt den End-Iterator zurück, der nicht zurückgestellt werden kann, da er von einer Debug-Assertion erfasst wird

Damit es so funktioniert, wie Sie es wollen, müssen Sie Shape vergleichen, nicht Shape*

Wie bereits in anderen Antworten erwähnt, boost::ptr_vector ist eine einfache Möglichkeit, dies zu erreichen.

6voto

xtofl Punkte 39285

Wie @David Pierre vorschlägt: find ist wertbasiert: es sucht im Bereich der Iteratoren nach einem Zeiger (z.B. 0x0F234420), der gleich dem Zeiger auf die new Circle(point(1,2),3) die Sie gerade erstellt haben. Da es sich um ein neues Objekt handelt, wird es nicht vorhanden sein.

Sie können dies umgehen, indem Sie find_if mit einem Operator, der die Objekte, auf die der Zeiger verweist, vergleicht.

Das Kriterium sollte jedoch in der Lage sein, zwischen den verschiedenen Formen zu unterscheiden.

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

2voto

Martin York Punkte 245363

Dies ist ein guter Grund, boost::ptr_vector zu verwenden.

Es geht nicht nur darum, dass Ihre Objekte zerstört werden müssen.
xtofl@: Du hast den virtuellen Destruktor vergessen.

Aber es lässt die Mitglieder auch wie Objekte aussehen, indem es Referenzen statt Zeiger zurückgibt. Dies ermöglicht es Ihnen, die Standard-Algorithmen viel natürlicher zu verwenden, als mit Zeigern in Ihrer "equal"-Funktion herumzuspielen (was sehr un-C++-artig ist).

#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;

}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X