Struct, members erst nach deklaration...



  • Hallo miteinander

    Ist es möglich ein struct vorerst ohne member-Variablen zu deklarieren, und erst ein paar Zeilen später die Members zu bestimmen?

    Bin gerade dabei die folgende Aufgabe zu lösen:

    "(5 Punkte) Der Strassen-Graph besteht aus zwei Grundelementen,
    town und street, die in der obigen Abbildung als rechteckige
    Tabellen dargestellt sind. Implementieren Sie diese als structs.
    Eine Stadt hat einen Namen und ein Array streets mit
    NSTREETS ausgehenden Strassen. Im Beispiel ist NSTREETS = 2,
    das Struct soll aber mit beliebigen Werten für NSTREETS
    zurechtkommen. Ausserdem gibt es ein Flag visited, dessen
    Bedeutung später ersichtlich wird. Eine Strasse hat eine
    bestimmte Länge und einen Link auf die Stadt, zu der sie führt.
    Durch die zirkuläre Abhängigkeit der beiden Strukturen ist es nötig,
    die eine vor der Definition der anderen zu deklarieren:

    struct town;
    Definieren Sie also erst street und anschliessend town.
    const int NSTREETS = 2;
    // hier Code einfügen

    Die eintscheidende Stelle habe ich fett markiert.
    Das problem ist ja, dass das struct town ein array von "street" structs beinhalted, und umgekehrt das struct "street" ein pointer auf "town" beinhaltet.
    Wenn man nun also town (inkl. members) zuerst deklariert reklamiert der compiler, da er "street" noch nicht kennt...
    Wie löst man das problem? (ich war bisher der ansicht, dass die deklaration der members sofort geschehen muss...)



  • Das Zauberwort für Google heißt "forward declaration".

    Also ja, das ist möglich. mit der Zeile

    struct town;
    

    sagt du dem Compiler, dass es irgendwo ein struct mit dem Namen "town" existiert. Bis zur Definition des structs kannst du es zwar nicht verwenden, aber du kannst zumindest Pointer/Referenzen als Member oder Funktionsparameter definieren.


  • Mod

    Du kannst das struct nicht ohne Member definieren und dich später umentschieden. Aber du kannst jederzeit deklarieren, dass es ein bestimmtes struct gibt, ohne zu definieren, wie es genau aussieht:

    struct foo;
    

    Für sehr viele Anwendungen, insbesondere für Pointer und Referenzen auf das struct, ist eine solche Deklaration (forward-declaration) ausreichend.



  • SeppJ schrieb:

    Du kannst das struct nicht ohne Member definieren und dich später umentschieden.

    Aber genau das wird doch in der Aufgabenstellung verlangt oder nicht?

    Also der code müsste irgendwie so aussehen:

    struct town;

    struct street {int dist; town* toTown;};

    town {string name; street streets[2];};

    Natürlich akzeptiert der Compiler die 3te Zeile nicht... Aber gemäss Aufgabenstellung muss es ja irgendwie gehen..
    wie macht man das jetzt genau?



  • struct town; 
    
    struct street {
      int dist;
      town* toTown;
    }; 
    
    struct town {
      string name;
      street streets[2];
    };
    


  • kaenzign schrieb:

    Natürlich akzeptiert der Compiler die 3te Zeile nicht... Aber gemäss

    struct town {string name; street streets[2];};



  • Danke euch.
    Mir war irgendwie nicht bewusst, dass das zulässig ist.
    Ich meine bei anderen Dateitypen geht das nicht:

    z.B:

    int x;
    int x = 1;
    

    akzeptiert mein Compiler nicht: " »int x« previously declared here|"

    Warum geht das denn bei Structs?



  • bei globalen vatriablen gehts auch

    extern int x;//deklaration
    int x;//definition
    

    und bei funktionen

    void f();//deklaration
    void f(){cout<<"hallo";}//definition
    


  • Einmal machst du nur den Namen bekannt (Deklaration), einmal definierst du, wie das struct genau aussieht.


  • Mod

    Dein int x; beschreibt nicht, wie ein int aussieht, sondern was x ist. Du müsstest das int x; eher mit

    struct foo { /* Irgendein Konstruktor, der Zahlen akzeptiert */ };
    
    foo x;
    foo x = 1; // Geht auch nicht, genau wie bei deinem Beispiel
    

    vergleichen.



  • Ok, jetzt verstehe ich, vielen Dank.

    Ohne jetzt extra dafür einen neuen Thread aufmachen zu wollen hätte ich doch noch eine kleine Frage zu der oben bescheriebenen Aufgabenstellung, genauer zu folgender Anmerkung:
    "Im Beispiel ist NSTREETS = 2, das Struct soll aber mit beliebigen Werten für NSTREETS zurechtkommen."

    Heisst das, dass man das street array dynamisch alloziieren muss? also:

    int NSTREETS = 2;
    
      struct town {
      string name;
      street* streets = new street[NSTREETS];
    };
    

    Habe das so probiert, der compiler meckert dann aber

    Wo liegt das problem?



  • Du solltest schon die Zeile mit MAX posten und sagen, was MAX ist.


  • Mod

    kaenzign schrieb:

    Heisst das, dass man das street array dynamisch alloziieren muss?

    Jain.
    Ja: Das muss dann dynamisch gemacht werden
    Nein: Das macht weder "man" und ganz bestimmt nicht "du", sondern std::vector. Selber new für Arrays zu nutzen ist immer die viel schlechtere Alternative zu vector, es hat nicht einmal einen einzigen Vorteil (denn vector macht effektiv das gleiche), dafür zahlreiche Nachteile (man kann sehr vieles daran sehr leicht falsch machen, vector macht garantiert alles richtig).

    Der Punkt, dass man bei manueller Speicherverwaltung sehr leicht viel falsch machen kann, gilt natürlich doppelt, wenn man noch Anfänger ist und sich mit den Grundlagen schwer tut. Also unbedingt mal vector angucken, falls noch nicht bekannt. Das ist die wohl wichtigste und meistgenutzte Klasse(nvorlage) der Standardbibliothek.



  • SeppJ schrieb:

    kaenzign schrieb:

    Heisst das, dass man das street array dynamisch alloziieren muss?

    Jain.
    Nein: Das macht weder "man" und ganz bestimmt nicht "du", sondern std::vector. Selber new für Arrays zu nutzen ist immer die viel schlechtere Alternative zu vector, es hat nicht einmal einen einzigen Vorteil (denn vector macht effektiv das gleiche), dafür zahlreiche Nachteile (man kann sehr vieles daran sehr leicht falsch machen, vector macht garantiert alles richtig).

    Hallo SeppJ
    Danke für den Tipp mit der vector Klasse, ich werde mich so bald wie möglich dahintersetzen.
    Die Sache ist nur, dass wir im Studium das noch nicht behandeld haben, und in der Aufgabenstellung verlangt wird, mit einem Array zu arbeiten...
    Desshalb würde ich doch noch gerne wissen, wie das mit einem Array funktionieren würde.

    EDIT:
    hier nochmal der ganze code:

    int main()
    {
    
    struct town;
    
    struct street
    {
        int dist;
        town* toTown;
    };
    
    int NSTREETS = 2;
    
    struct town
    {
        string name;
        street* streets = new street[NSTREETS];
    };
    
        return 0;
    }
    

    Der Compiler gibt volgende fehlermeldung aus:
    »NSTREETS« kann nicht in Konstanten-Ausdruck auftreten|
    »new« kann nicht in einem Konstanten-Ausdruck auftreten|
    ISO-C++ verbietet Initialisierung des Elementes »streets« [-fpermissive]|
    »streets« wird statisch gemacht [-fpermissive]|
    ungültige Initialisierung innerhalb der Klasse des statischen Datenelements vom nicht eingebauten Typen »main()::street*«|
    ||=== Build finished: 5 errors, 0 warnings ===|

    Verstehe nicht, wo das problem liegt..



  • Dein Code passt nicht zur Fehlermeldung bzw. ist unvollständig.


Anmelden zum Antworten