Mehrdimensionale Objektstruktur



  • Hallo,

    ich möchte eine mehrdimensionale objektstruktur aufbauen, habe jedoch das problem, das die zuweisung nicht funktioniert.

    class GraphEntry;
    
    class MatrixGraph {
    
      public:
        /* constructor, destructor, ... */
    
        void init();
        void addGraphEntry(GraphEntry *entry, int row, int col);
    
      private:
        GraphEntry **matrix;
        int maxSize = 3;
    }
    
    void MatrixGraph::init() 
    {
      if (maxSize > 0) {
        matrix = new GraphEntry*[maxSize];
        for (int i = 0; i < maxSize; i++)
          matrix[i] = new GraphEntry[maxSize];
      }
    }
    
    void MatrixGraph::addGraphEntry(GraphEntry *entry, int row, int col)
    {
      if (row < maxSize && col < maxSize) {
        matrix[row][col] = entry;
      }
    }
    

    In der methode addGraphEntry möchte ich einen eintrag einer bestimmten position in der matrix zuweisen, jedoch bemängelt der compiler das mit der meldung:

    no match for ‘operator=’ (operand types are ‘GraphEntry’ and ‘GraphEntry*’)

    In der klasse GraphEntry habe ich den zuweisungsoperator überschrieben.

    Kann mir jemand sagen, wo ich einen fehler gemacht habe?

    Weiters ist mir bewusst, das es stl container gibt, aber ich muss mit arrays arbeiten.

    Danke.



  • Die Fehlermeldung kann doch klarer nicht sein.
    Du versuchst einem GraphEntry einen GraphEntry* zuzuweisen.
    Du musst den GraphEntry-Zeiger auf der rechten Seite dereferenzieren.

    matrix[row][col] = *entry;
    


  • Danke, das ergibt jetzt sinn.

    Was kann ich machen, damit ich den zeiger nicht dereferenzieren muss, sondern direkt speichern kann?



  • Steini79 schrieb:

    Was kann ich machen, damit ich den zeiger nicht dereferenzieren muss, sondern direkt speichern kann?

    Ein 2d GraphEntry-Pointer array, aktuell hast du ein 2d GraphEntry array.



  • tkausl schrieb:

    Ein 2d GraphEntry-Pointer array, aktuell hast du ein 2d GraphEntry array.

    Ok, danke, und wie?

    Was ich möchte ist, ich bekomme einen zeiger auf ein GraphEntry, das irgendwo außerhalb erstellt wurde. Ich möchte jetzt diese adresse an kreuzungspunkt von zeile und spalte in der matrix speichern.



  • Steini79 schrieb:

    Danke, das ergibt jetzt sinn.

    Was kann ich machen, damit ich den zeiger nicht dereferenzieren muss, sondern direkt speichern kann?

    Du könntest deine Methode addGraphEntry() dahingehend ändern, dass sie keinen Pointer erwartet, sondern ein "Value", bzw. für deinen derzeitigen Code sinnvoll eine konstante Referenz darauf:

    void MatrixGraph::addGraphEntry(const GraphEntry& entry, int row, int col)
    {
        ...
        matrix[row][col] = entry;
    }
    

    Finnegan



  • Das geht leider nicht, die signatur der methode ist vorgegeben

    void addGraphEntry(GraphEntry *entry, int row, int col);
    

    Aber danke für den tipp!



  • Steini79 schrieb:

    Danke, das ergibt jetzt sinn.

    Was kann ich machen, damit ich den zeiger nicht dereferenzieren muss, sondern direkt speichern kann?

    Deine matrix entsprechend definieren. Im Moment speichert die GraphEntry-Objekte und keine Zeiger auf Graphentry-Objekte.

    Der Compiler wäre mit

    GraphEntry ***matrix;
    

    zufriedengestellt.

    Schön ist aber anders.



  • Danke, das ist jetzt also ein zeiger auf ein array mit zeigern auf objekte.

    Und löschen kann ich das ganze im destrukter wie folgt?

    for (int i = 0; i < maxSize; i++) {
        delete[] matrix[i];
      }
      delete[] matrix;
    

    Oder habe ich da wieder einen denkfehler?



  • Du hast dann ein 2 dimensionales Array mit Zeigern auf GraphEntry-Objekte

    GrapEntry*[3][3]

    Deine Init-Methode passt dann nicht mehr und abräumen tust du nur den für die Zeiger angeforderten Speicher.
    Die GraphEntry-Objekte selber räumst Du nicht ab.
    Normalerweise räumt der die GraphEntry-Objekte auf, der sie auch angelegt hat.
    Außer das Design ist so dass die nur angelegt werden und Du die dann selber verwalten musst.
    Fragen über Fragen.

    Du bist wirklich sicher keine STL-Container und Smartpointer verwenden zu wollen?



  • STL container verwenden würde ich schon wollen, nur gehts in der übung um arrays und zeiger. 🙂

    Ich habe das jetzt folgendermaßen geändert:

    GraphEntry ***matrix;
    
    void MatrixGraph::init() 
    {
      if (maxSize > 0) {
        matrix = new GraphEntry**[maxSize];
        for (int i = 0; i < maxSize; i++)
          matrix[i] = new GraphEntry*[maxSize];
      }
    }
    

    Nur um sicher zu gehen, ich habe hier einen zeiger, der auf ein array zeigt, in welchem wieder zeiger sind die auf ein array zeigen? Hab ich das jetzt so richtig verstanden?

    Wenn ich das jetzt wieder alles sauber löschen möchte

    for (int i = 0; i < maxSize; i++) {
        delete[] matrix[i]; //hier entferne ich die arrays in den arrays
      }
      delete[] matrix; //hier entferne ich die arrays
    

    Lieg ich soweit richtig? Die klasse MatrixGraph soll mehr oder weniger die ownership der GraphEntry objekte übernehmen, unabhängig davon, ob das im der realität wirklich so gemacht wird. Daher soll auch alles sauber wieder gelöscht werden.



  • Bevor Du die Arrays mit delete[] zerstörst musst Du erst durch beide Dimensionen iterieren und delete für die GraphEntry-Zeiger aufrufen wenn Deine MatrixGraph-Klasse den Besitz der Objekte übernommen hat.


  • Mod

    Dir ist schon klar, dass deine Matrix sich zu einer "richtigen" 2D-Matrix verhält wie

    ####
    ########
    ##
    #########
    ######
    

    zu

    ####
    ####
    ####
    ####
    

    ?



  • SeppJ schrieb:

    Dir ist schon klar, dass deine Matrix sich zu einer "richtigen" 2D-Matrix verhält wie

    ####
    ########
    ##
    #########
    ######
    

    Manch einer hat da sogar folgendes Bild vor Augen:

    #########
    
                            ##                    ####                                    
    
                             ######
    

    😉
    SCNR,
    Finnegan


  • Mod

    Das ist dann das Speicherlayout, ich habe das logische Layout dargestellt 🙂 . Das Speicherlayout der "richtigen" Matrix wäre (im Kontrast zu dem was der Threadersteller macht, was in deinem Bild dargestellt ist):

    ################
    

Anmelden zum Antworten