Problem mit Deklaration bei C++



  • Hallo Leute,

    ich hänge an einem doofen Problem und komme nicht weiter. Ich habe zwei Klassen, die sich gegenseitig aufrufen und bekomme dazu folgenden Fehler:

    auftrag.h:18:19: error: ‘Kunde’ has not been declared
    auftrag.h:19:5: error: ‘Kunde’ does not name a type
    auftrag.h:23:5: error: ‘Kunde’ does not name a type

    Bei folgendem Quellcode:

    auftrag.h

    #ifndef AUFTRAG_H
    #define	AUFTRAG_H
    
    #include <string>
    #include <vector>
    #include "kunde.h"
    
    using std::string;
    
    class Auftrag {
    public:
        Auftrag(string s);
        ~Auftrag( );
    
        void print();
        const string& getID();
    
        void setKunde(Kunde* k);
        Kunde* getKunde();
        void delPtrAusKunde();
    private:
        string id;
        Kunde* Kunde;
    };
    
    #endif
    

    kunde.h

    #ifndef KUNDE_H
    #define	KUNDE_H
    
    #include <string>
    #include <vector>
    #include "auftrag.h"
    
    using std::string;
    using std::vector;
    
    class Kunde {
    public:
        Kunde(string s);
        ~Kunde();
    
        void print();
        const string& getName();
    
        void addAuftrag(Auftrag *a);
        vector<Auftrag*>& getAuftraege();
        void cancelAuftrag(Auftrag *a);
    private:
        string name;
        vector<Auftrag*> vMyAuftr;
    };
    
    #endif
    

    main.cpp

    #include <iostream>
    #include "kunde.h"
    #include "auftrag.h"
    
    using namespace std;
    
    int main() {
    
        return 0;
    }
    

    Ich hab doch beide Deklarationen bei den h-Dateien nochmals eingebunden, aber bekomme trotzdem den Fehler ... Kann mir jemand helfen?

    Danke schonmal! Gruß Marc



  • Ich denke du brauchst in auftrag.h eine Forward Declaration fuer die Klasse Kunde, damit der Compiler weiss, dass Kunde eine Klasse ist, die sich irgendwo befindet.

    #ifndef AUFTRAG_H 
    #define    AUFTRAG_H 
    
    #include <string> 
    #include <vector> 
    #include "kunde.h" 
    
    using std::string;
    
    class Kunde; // Forward Declaration
    
    class Auftrag { 
    public: 
        Auftrag(string s); 
        ~Auftrag( ); 
    
        void print(); 
        const string& getID(); 
    
        void setKunde(Kunde* k); 
        Kunde* getKunde(); 
        void delPtrAusKunde(); 
    private: 
        string id; 
        Kunde* Kunde; 
    }; 
    
    #endif
    

  • Mod

    Gegenseitiges Einbinden von Headern geht immer schief. Du brauchst eine Vorwärtsdeklaration:

    #ifndef AUFTRAG_H
    #define    AUFTRAG_H
    
    #include <string>
    #include <vector>
    
    class Kunde;
    
    using std::string;
    
    class Auftrag {
    public:
        Auftrag(string s);
        ~Auftrag( );
    
        void print();
        const string& getID();
    
        void setKunde(Kunde* k);
        Kunde* getKunde();
        void delPtrAusKunde();
    private:
        string id;
        Kunde* Kunde;
    };
    
    #endif
    
    #ifndef KUNDE_H
    #define    KUNDE_H
    
    #include <string>
    #include <vector>
    
    class Auftrag;
    
    using std::string;
    using std::vector;
    
    class Kunde {
    public:
        Kunde(string s);
        ~Kunde();
    
        void print();
        const string& getName();
    
        void addAuftrag(Auftrag *a);
        vector<Auftrag*>& getAuftraege();
        void cancelAuftrag(Auftrag *a);
    private:
        string name;
        vector<Auftrag*> vMyAuftr;
    };
    
    #endif
    


  • Hallo,

    vielen Dank schonmal, aber das hatte ich auch versucht und da kommt folgender Fehler:

    In file included from main.cpp:3:0:
    auftrag.h:24:12: error: declaration of ‘Kunde* Auftrag::Kunde’
    kunde.h:13:13: error: changes meaning of ‘Kunde’ from ‘class Kunde’

    😞



  • Kunde* Kunde;
    

    Du deklarierst ein Object Kunde mit Typ Zeiger auf Kunde - doppelte Bedeutung des Bezeichners "Kunde". Nenn das Objekt einfach anders.



  • Super, vielen Dank 🙂



  • Was für ein grässliches Denglisch.



  • Ich hab noch ein weites Problem und zwar baue ich gerade die Methode "print" von Kunde:

    void Kunde::print() {
        cout << "Kunde: " << name << endl << "Auftraege: ";
        for(int i = 0; i < vMyAuftr.size(); i++)
            cout << (*(vMyAuftr.at(i))).getID() << " ";
    }
    

    Da bekomm ich folgenden Fehler:

    kunde.h:46:36: error: invalid use of incomplete type ‘struct Auftrag’
    kunde.h:7:7: error: forward declaration of ‘struct Auftrag’


  • Mod

    In der Implementierung reicht die Vorwärtsdeklaration nicht mehr. Da musst du dann wirklich die auftrag.h einbinden.



  • Klar, in kunde.h hast du (wg. Vermeidung zyklischer Einbindung der Header) nur eine Forward Declaration. Um "Auftrag" verwenden zu können, brauchst du aber die Definition der Klasse, die du erst mit dem include bekommst.
    Um nicht wieder in zyklisches einbinden zu laufen, legst du eine Datei "kunde.cpp" an, in die du die Definition von Kunde::print() vornimmst. Dort kannst du gefahrlos kunde.h und auftrag.h einbinden.

    @SeppJ: er implementiert gerade in kunde.h (laut Fehlermeldung)



  • Evtl. könnte man bei den Funktions(deklarationen)auch besser Referenzen statt Zeiger verwenden?



  • redrew99 schrieb:

    Evtl. könnte man bei den Funktions(deklarationen)auch besser Referenzen statt Zeiger verwenden?

    Evtl. könnte man bei den Funktions(deklarationen)auch besser die Zeiger lassen?



  • mal ganz ehrlich: referenzen in klassen verwenden? das hab ich nie gebraucht bis jetzt, ist auch recht unflexibel aus meiner sicht. klar es gibt sicherlich das ein oder andere anwendungsgebiet, aber da gibts bessere alternativen.

    und zum zeiger: da gibts wahrlich bessere alternativen in diesem fall, und sei es nur ein smart pointer aus der STL. aber am besten ist immer noch, gar kein zeiger



  • Er meinte sicherlich bei

    void setKunde(Kunde* k);
    

    mit dem Gebetsmühlenargument, da der Kunde nicht 0 sein darf, müsse man das so per Referenz anzeigen.

    void setKunde(Kunde& k);
    

    Anderenfalls müsse man im Code von setKunde gegen 0 prüfen.
    Das ist jedesmal falsch, wenn dieses Argument kommt.

    Und diesmal besonders

    bla.setKunde(*new Kunde(...));
    

    :xmas2: :xmas2:



  • oh mist, kann auch sein. hab mir den quellcode nicht aufmerksam angeguckt -.-'


Anmelden zum Antworten