Vorwärtsdeklaration



  • Hallo,

    ich habe gerade ein Problem mit der (meiner Meinung nach) bescheuerten Vorwärtsdeklaration des C++ Single-Pass-Compilers.
    Ich habe eine Anzahl an structs, die alle untereinander verwoben sind. Ich versuche es mal an einem Beispiel zu erklären:

    //Body.h
    #ifndef BODY_HEADER
    #define BODY_HEADER
    
    #include "Contact.h"
    
    struct Body{
       bool isUnder(Contact &c);
    };
    #endif
    
    //Contact.h
    #ifndef CONTACT_HEADER
    #define CONTACT_HEADER
    
    struct Contact{
       Body *axBodies[2];
    };
    #endif
    

    Wenn ich jetzt in meinem Hauptprogramm die Datei "Body.h" lade (mit #include), dann gibt es in der Zeile "Body *axBodies[2]" den Fehler "error C2061: Syntaxfehler: Bezeichner 'Body' ".

    Ich habe dann folgendes versucht:

    //main.h
    #include <iostream>
    #include <math.h>
    #include <stdlib.h>
    
    using namespace std;
    
    struct Body;
    struct Contact;
    
    #include "Body.h"
    #include "Contact.h"
    

    Und im Hauptprogramm dieses "Main.h" laden (ich habe die #include aus Body.h rausgenommen). Dann kriege ich in der Zeile "bool isUnder(Contact &c)" die Fehlermeldung: "error C2061: Syntaxfehler: Bezeichner 'Contact' ".

    Kann mir jemand helfen, wie ich dies richtig anordne oder aufbaue, damit der Compiler nicht auf die Barrikade geht und seine Arbeit macht?

    Ich hoffe das Problem ist klar genug geschildert und lösbar.
    MfG,
    Darth



  • Die beiden Header müssen sich nicht "inkludieren":

    //Body.h
    #ifndef BODY_HEADER
    #define BODY_HEADER
    
    // Forward-Deklaration von Contact
    struct Contact;
    
    struct Body{
       bool isUnder(Contact &c);
    };
    #endif
    
    //Contact.h
    #ifndef CONTACT_HEADER
    #define CONTACT_HEADER
    
    // Forward-Deklaration von Body
    struct Boy;
    
    struct Contact{
       Body *axBodies[2];
    };
    #endif
    

    Und hier hast du richtig Murks gebaut:

    • Verwende cmath und cstdlib statt der C-Headers - Die sind kein Standard!
    • using namespace std; in einem Header? - NIEMALS!!!!
    //main.h
    #include <iostream>
    #include <cmath>
    #include <cstdlib>
    
    #include "Body.h"
    #include "Contact.h"
    

    Ich habs jetzt nicht ausprobiert, aber so sollte es funktionieren...
    Viel Glück



  • #include <iostream>
    #include <cmath>
    #include <cstdlib>
    #include "Body.h"
    #include "Contact.h"
    

    gehört auch nicht in den Header.
    Nur Dinge inkludieren, die unbedingt für den Header notwendig sind!
    Hier kann der Header also leer bleiben, bzw. ist überflüssig.



  • Hallo daersc,

    deinen Ansatz habe ich auch schon versucht. Aber da gibt mir der Compiler den Fehler aus, dass ich das "undefinierte struct Contact" (bzw Body) verwende. Er KENNT zwar den struct, aber der ist ja noch "leer" dort.

    Das iostream etc hab ich aus dem Header genommen, danke für den Tipp.

    MfG,
    Darth



  • Darth schrieb:

    Aber da gibt mir der Compiler den Fehler aus, dass ich das "undefinierte struct Contact" (bzw Body) verwende. Er KENNT zwar den struct, aber der ist ja noch "leer" dort.

    Dann hast du nicht den ganzen Code gepostet.
    Auf Klassenelemente kannst du natürlich erst dann zugreifen, wenn die gesamte Klassenstruktur bekannt ist. Das ist erst in der .cpp-Datei der Fall.



  • Athar schrieb:

    Auf Klassenelemente kannst du natürlich erst dann zugreifen, wenn die gesamte Klassenstruktur bekannt ist. Das ist erst in der .cpp-Datei der Fall.

    Was meinst du damit?

    @Darth
    Du brauchst im Header Contact die Vorwärtsdeklaration von Body. Allerdings kannst du damit nur Zeiger halten. Sobald du irgendwie dereferenzieren willst, ist es mit dem Ansatz aus. Mit dem Array axBodies hälst du bisher auch nur Zeiger, daher gibt es mit dem geposteten Code an der Stelle noch keine Probleme.

    Der Header Body muss den Header Contact inkludieren, weil du dort nicht nur mit Zeigern auf Contact arbeitest, somit müssen die gesamten Objekteigenschaften von Contact bekannt sein.

    //Contact.h
    #ifndef CONTACT_HEADER
    #define CONTACT_HEADER
    
    // Forward-Deklaration von Body
    struct Body;
    
    struct Contact{
       Body *axBodies[2];
    };
    #endif
    
    //Body.h
    #ifndef BODY_HEADER
    #define BODY_HEADER
    
    #include "Contact.h"
    
    struct Body{
       bool isUnder(Contact &c);
    };
    #endif
    
    //main.h
    #include <iostream>
    #include <cmath>
    #include <cstdlib>
    
    #include "Body.h"
    #include "Contact.h"	
    
    using namespace std;
    


  • hmpf schrieb:

    Athar schrieb:

    Auf Klassenelemente kannst du natürlich erst dann zugreifen, wenn die gesamte Klassenstruktur bekannt ist. Das ist erst in der .cpp-Datei der Fall.

    Was meinst du damit?

    In Contact.cpp und Body.cpp sind jeweils beide Header eingebunden, also kann man auch auf Member der jeweils anderen Klasse zugreifen.



  • Athar schrieb:

    In Contact.cpp und Body.cpp sind jeweils beide Header eingebunden, also kann man auch auf Member der jeweils anderen Klasse zugreifen.

    Weiß zwar noch immer nicht, worauf du hinaus willst, aber ich muss ja nicht alles verstehen. 🙂



  • Hallo,

    danke für die Hilfe.

    @Athar,
    ja, ich habe nicht den ganzen Code gepostet. Das wären etwa um die 1500 Zeilen, ich habe es auf das wesentliche gekürzt, möglich dass ich dabei etwas wichtiges vergessen habe.

    @hmpf,
    dass ich nur Zeiger verwenden darf wusste ich nicht, es stimmt dass ich da mit Referenzen arbeite (und auch andernorts). Auf Membervariabeln greife ich eigentlich nirgends zu, weil ich im h-File nur die Funktionsdeklarationen aber keine Rümpfe habe.

    So, nun da mir das erklärt wurde, kann ich versuchen das richtig zu basteln 🙂 Ich danke nochmal für die Hilfe.

    Mit freundlichen Grüssen,
    Darth



  • Darth schrieb:

    @hmpf,
    dass ich nur Zeiger verwenden darf wusste ich nicht, es stimmt dass ich da mit Referenzen arbeite (und auch andernorts). Auf Membervariabeln greife ich eigentlich nirgends zu, weil ich im h-File nur die Funktionsdeklarationen aber keine Rümpfe habe.

    Referenzen und Zeiger verhalten sich gleich, was die Abhängigkeiten betrifft. Du benötigst die Definition des Typen erst bei der Dereferenzierung.



  • Hallo,

    ach Mensch.. kaum hat man das Gefühl, man habe das Zeug verstanden kommt der Nächste und verwirrt einen wieder. Danke dafür Nexus 😃

    Dennoch scheint es zu funktionieren, wenn ich von "under(Contact &c)" zu "under(Contact *c)" wechsle 😕 Da ich im Moment keinen grossen Unterschied zwischen Pointer und Referenzen sehe, ist es mir eigentlich relativ egal welche Variante ich verwende.

    So.. Thx 🙂

    MfG,
    Darth


Anmelden zum Antworten