Objekte in STL-Liste speichern funktioniert nur mit tmp. Objekt

Atlanx

Mitglied
(Statische, globale) Objekte in Liste kopieren.
-------------------------------------------------------------------

IDE: Borland C++ Builder 6

Ich hatte heute ein Problem damit ein Objekt (global) in einer STL-Liste abzulegen.
Inzwischen habe ich zwar eine Lösung gefunden, mit der es funktioniert, aber ich verstehe immer noch nicht, wieso mein erster Ansatz nicht funktioniert hat.

Vielleicht kann mir hier jemand sagen, worin mein Fehler liegt bzw was genau die Zeile
PolygonList.push_back(MyPolygon) macht, denn eigentlich es würde dadurch das Objekt in der Liste gespeichert und z.B. NICHT nur ein Zeiger.


Dies sind die entsprechenden Zeilen aus dem Quellcode:
Code:
// globale Variablen anlegen
list <TypePoly> PolygonList;   // STL-Liste
TypePoly MyPolygon;             //(global = Statisches Objekt)

Code:
void __fastcall TForm1::FormMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)

Es geht nicht so:
Code:
 PolygonList.push_back(MyPolygon); // Polygon der Liste hinzufuegen
und auch nicht so:
Code:
 if (a=b) 
 {
    TypePoly MyPolygon2; 
    MyPolygon2 = MyPolygon;
    PolygonList.push_back(MyPolygon2); // Polygon der Liste hinzufuegen
 }
Sondern so:
Code:
 TypePoly MyPolygon2;
 if (a=b) 
 {		
    MyPolygon2 = MyPolygon;
    PolygonList.push_back(MyPolygon2); // Polygon der Liste hinzufuegen
 }
Code:
 }


Fragen:
1) warum geht der erste und zweite Ansatz nicht.
2) Was genau tut PolygonList.push_back(MyPolygon2);

----------------------------------------------------------------------------------------------------------------------
Es folgt nochmal der funktionierende Quellcode, aber ausführlicher,
falls das da oben zu wenig sein sollte:
----------------------------------------------------------------------------------------------------------------------
Code:
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#include "IGL.h"
#include <list>         // I want to use the STL list container class
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner): TForm(Owner) { }

// Strukturen
struct IntersectionPoint // Schnittpunkt
{
        int             EdgeNr;
        double          Lambda;
        TypePoint       Intersection;
};
// Listen
list <IntersectionPoint> IntersectionList;
list <TypePoly> PolygonList;

// Polygon anlegen
TypePoly MyPolygon;

//---------------------------------------------------------------------------
void __fastcall TForm1::FormActivate(TObject *Sender) 
{
    PolygonList.clear();
    InitGraphics(); 
}

// Durchlaeuft alle Punkte des Polygons
void CreateAndFillSubPolygons(TypePointPair Line)
{
         // Step 1: Create the IntersectionList of Line with MyPolygon.
        IntersectionList.clear();

        // Get MyPolygon from PolygonList and delete it from PolygonList
        TypePoly TempPoly = PolygonList.back();
        MyPolygon = TempPoly;

        PolygonList.pop_back();
     .....
}

////////////////////////////////////////////////////////////////////////////////
// MouseUp //////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
bool MakePoly = true;
void __fastcall TForm1::FormMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
{
        TypePoly MyPolygon_tmp;

        TypePoint P = HCToTypePoint(X,Y); // angeklickten Punkt ermitteln

        if (MakePoly)         //-Any mousekey
        // The user is creating the 1. polygon:
        {
                MyPolygon.AppendVertex(P);
                MyPolygon.DrawAsPolyline();
        }
        else // The user is creating the line to cut the polygon:
        { ... 
            CreateAndFillSubPolygons(Line); 
        ....}       
        if (Button == mbRight)  //-Right mousekey
        {
                MakePoly = false;
                MyPolygon.DrawAsPolygon();

                MyPolygon_tmp = MyPolygon;
                PolygonList.push_back(MyPolygon_tmp);
        }
}
//---------------------------------------------------------------------------
//End

Vielen Dank. :)
 
Hi.

Wie kommst du denn darauf das es nicht geht?! Soll heißen: wie macht sich das denn bemerkbar? Welche Fehlermeldung kriegst du oder was genau entspricht nicht deinen Erwartungen?

Gruß
 
Das sollte beides genau das gleiche tun. In beiden Fällen wird durch push_back eine Kopie des Objektes (mit dem Copyconstructor erstellt) in die Liste eingefügt.

Evtl. hast du da den Default-Copyconstructor von deinem Objekt und der tut nicht, was er tun sollte.

Beachte die Regel der Drei: Wenn dein Objekt einen Destruktor, Copy-Construktor oder Zuweisungsoperator benötigt, dann benötigt es alle drei!
 
deepthroat hat gesagt.:
Hi.
Wie kommst du denn darauf das es nicht geht?! Soll heißen: wie macht sich das denn bemerkbar? Welche Fehlermeldung kriegst du oder was genau entspricht nicht deinen Erwartungen?
Gruß

Ich führe mit den Daten(Punkte des Polygons) aus dem Polygonobjekt Berechnungen durch.
Und wenn ich es nicht wie beschrieben in der Liste ablege, semmelt mir das Programm in einer Unterfunktion der IGL.cpp mit einer "Floating point division by zero" ab.
 
Endurion hat gesagt.:
Evtl. hast du da den Default-Copyconstructor von deinem Objekt und der tut nicht, was er tun sollte.
Beachte die Regel der Drei: Wenn dein Objekt einen Destruktor, Copy-Construktor oder Zuweisungsoperator benötigt, dann benötigt es alle drei!

Die IGL.cpp enthaelt eine Klasse TypePoint mit folgenden Methoden:
Code:
//THE-TypePoly-CLASS-----------------------------------------------------------------

void TypePoly::SetDefaults() // Initialize a TypePoly object from an array.
{
        // Set the defaults:
        mNrVertices = 0;
        start = NULL;
        end = NULL;
        mNrSteps = 5;
        Closed = false;
        Fill = false;
        Smooth = false;
        mLambda = 0.4;
        iSelected = 0;
        FillColour = GREEN;
}

TypePoly::TypePoly(int Nr, TypePoint Vert[]) // Initialize a TypePoly object from an array.
{
        // Set the defaults:
        SetDefaults();
        // Add the supplied vertices:
        for (int iVert = 0; iVert < Nr; iVert++)
                AppendVertex(Vert[iVert]);
}

// We need a copy constructor:
void TypePoly::operator=(const TypePoly &AnotherPolyObject)
{
        if (this != &AnotherPolyObject)     // Don't copy anobject to itself!
        {
                DeleteAll();
                Closed = AnotherPolyObject.Closed;
                Fill = AnotherPolyObject.Fill;
                Smooth = AnotherPolyObject.Smooth;
                FillColour = AnotherPolyObject.FillColour;
                int NrV = AnotherPolyObject.NrVertices();
                for (int iVert = 1; iVert <= NrV; ++ iVert) {
                        AppendVertex(AnotherPolyObject.Vertex(iVert));
                }
        }
}

void TypePoly:: DeleteAll()
{
        PointNodePtr ptr1 = start;
        PointNodePtr ptr2 = NULL;
        for (int i = 1; i < mNrVertices; ++i)
        {
                ptr2 = ptr1;
                ptr1 = ptr1->next;
                delete ptr2;
        }
        delete ptr1;
        SetDefaults();
}

TypePoly::~TypePoly()
{
//ShowMessage("TypePoly destructor");
//        DeleteAll();
//        start = NULL;
//        end = NULL;
//        mNrVertices = 0;
}

1) Zuweisungsoperator [fehlt] oder was meinst du damit?
Meinst du den Konstruktor: TypePoly(int Nr, TypePoint Vert[]) ?
2) Copy-Construktor [ok] (vorhanden, und sieht eigentlich ok aus, oder?)
3) Destructor vorhanden [ok] (auch wenn alles auskommentiert ist, wieso auch immer

Vielen Dank. :)
 
Zuletzt bearbeitet:
Äh, der Kommentar im Code ist falsch:
Das mit operator= ist der Zuweisungsoperator. Es fehlt der Copy-Construktor. Der müsste so aussehen:

TypePoly::TypePoly( const TypePoly &AnotherPolyObject)

und vom Inhalt her dann eigentlich dasselbe tun wie der Zuweisungsoperator.
 
Nebenbei bemerkt:
Oben sehe ich in deinem Code die Bedingung "if (a = b) ..."
Prüf mal, ob nicht "if (a == b) ..." beabsichtigt ist. Ansonsten ist es schlechter Stil.

Grüße
Onkel Schuppig
 
Onkel Schuppig hat gesagt.:
Nebenbei bemerkt:
Oben sehe ich in deinem Code die Bedingung "if (a = b) ..."
Prüf mal, ob nicht "if (a == b) ..." beabsichtigt ist. Ansonsten ist es schlechter Stil.

Eigentlich steht da im Quelltext bei mir
if (Button == mbRight)

Aber ich wollte den Code so einfach wie möglich darstellen, nur auf die Logik konzentriert.

Hier also nochmal der ganze Code der Funktion, aber das verwirrt eher mehr als es hilft:

Code:
bool MakePoly = true;
TypePointPair Line;   // Linie anlegen
int stage = 0;

void __fastcall TForm1::FormMouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
{
        Label1->Visible = false;
        TypePoint P = HCToTypePoint(X,Y); // angeklickten Punkt ermitteln
        DrawMarkerAt(P);

        TypePoly MyPolygon_tmp;

        //-Any mousekey
        if (MakePoly)
        // The user is creating the 1. polygon:
        {
                MyPolygon.AppendVertex(P);
                MyPolygon.DrawAsPolyline();
        }
        else
        // The user is creating the line to cut the polygon:
        {
                ++stage;
                if (stage == 1)
                        Line.P1 = P;
                else if (stage == 2)
                {
                   // EraseGraphics();
                        Line.P2 = P;
                        DrawInfiniteLine(Line);
                        CreateAndFillSubPolygons(Line);
                        stage = 0;
                }
        }
        //-Right mousekey
        if (Button == mbRight)
        {
                MakePoly = false;
                MyPolygon.DrawAsPolygon();

                MyPolygon_tmp = MyPolygon;
                PolygonList.push_back(MyPolygon_tmp);
                //MyPolygon.DeleteAll();
        }
        ShowGraphics();
        Label1->Visible = true;
        Label2->Visible = true;
}
 
deepthroat hat gesagt.:
Hi.
Wenn dein Problem gelöst ist, dann markier doch einfach das Thema als erledigt.
Oder gibt's noch ein Problem?
Gruß

Das Problem war ja schon gelöst, als ich den Tread hier angefangen habe.
Es geht mir darum zu verstehen, wieso mein erster und zweiter Ansatz nicht funktioniert.

Wenn du mir das sagen kannst, DANN können wir den Thread schließen.
Bisher war aber keiner in der Lage mir zu sagen, was an meinem ersten Ansatz falsch ist.
 
Zurück