Expected class name before '{' token - Error mit OOP



  • Hallo,

    ich möchte gerne eine Klasse von einer anderen erben lassen. Hierzu habe ich folgende Codes erstellt:

    //main.cpp
    #include "includes.hpp"
    
    int main()
    {
        Katze testKatze("Muster",150,"grau");
        cout << testKatze.getGroesse();
        return 0;
    }
    
    //includes.hpp
    #include <iostream>
    #include <string.h>
    
    using namespace std;
    
    #include "tier.hpp"
    #include "katze.hpp"
    
    //tier.hpp
    #ifndef _H_TIER_
    #define _H_TIER_
    
    #include "includes.hpp"
    
    class Tier {
        private:
            string itsName;
            unsigned short int itsSize;
    
        public:
            Tier(string name, unsigned short int groesse);
            string getName();
            unsigned short int getGroesse();
    };
    
    #endif
    
    //tier.cpp
    #include "tier.hpp"
    
    Tier::Tier(string name, unsigned short int groesse) {
        itsName = name;
        itsSize = groesse;
    }
    
    unsigned short int Tier::getGroesse() {
        return itsSize;
    }
    
    string Tier::getName() {
        return itsName;
    }
    
    //katze.hpp
    #ifndef _H_KATZE_
    #define _H_KATZE_
    
    #include "includes.hpp"
    
    class Katze : public Tier {
        private:
            string itsFellfarbe;
    
        public:
            Katze(string name, unsigned short int groesse, string fellfarbe);
            string getFellfarbe();
    };
    
    #endif
    
    //katze.cpp
    #include "katze.hpp"
    
    Katze::Katze(string name, unsigned short int groesse, string fellfarbe) {
        itsName = name;
        itsGroesse = groesse;
        itsFellfarbe = fellfarbe;
    }
    
    Katze::getFellfarbe() {
        return itsFellfarbe;
    }
    

    Leider bekomme ich beim kompilieren mit MinGW folgenden Fehler:

    D:\workspace\test\katze.hpp|7|error: expected class-name before '{' token|
    

    Es wird ein Klassenname in der Zeile 7 aus der katze.hpp erwartet. Habe ich evtl. etwas vergessen zu includen?

    Vielen Dank,

    Blu-Ray



  • Aua, da gibt es derbe Fehler. Du greifst auf private member der Basisklasse zu, vergisst bei Katze::getFellfarbe() den return Typ in der Signatur, ... und dein includes.hpp ist schlechter Stil.



  • Sry, das mit Katze::getFellfarbe hab ich gerade nicht gesehen.

    //katze.hpp
    #include "katze.hpp"
    
    Katze::Katze(string name, unsigned short int groesse, string fellfarbe) {
        itsName = name;
        itsGroesse = groesse;
        itsFellfarbe = fellfarbe;
    }
    
    string Katze::getFellfarbe() {
        return itsFellfarbe;
    }
    

    Du greifst auf private member der Basisklasse zu

    Wie kann ich sonst auf die Elemente zugreifen? Ich möchte die Eigenschaften nicht public machen.

    und dein includes.hpp ist schlechter Stil

    Soll ich stattdessen die Files einzeln includen?



  • Wie waere es mit dem Aufruf des Basisklassenkonstruktors. Und "es sollte nur inkludiert werden, was auch benutzt wird". Auch ein globales using namespace std ist bei groesseren Sachen eher hinderlich.



  • Wobei eher hinderlich eher tödlich bedeutet.
    Simon



  • Du meinst so?

    //katze.hpp
    #ifndef _H_KATZE_
    #define _H_KATZE_
    
    #include "includes.hpp"
    
    class Katze : public Tier {
        private:
            string itsFellfarbe;
            Tier itSelf;
    
        public:
            Katze(string name, unsigned short int groesse, string fellfarbe);
            string getFellfarbe();
    };
    
    #endif
    
    //katze.cpp
    #include "katze.hpp"
    
    Katze::Katze(string name, unsigned short int groesse, string fellfarbe) {
        itSelf = Tier(name,groesse);
        itsFellfarbe = fellfarbe;
    }
    
    string Katze::getFellfarbe() {
        return itsFellfarbe;
    }
    

    In welcher Funktion soll ich den Konstruktor von Tier aufrufen?

    //edit: Ich habe an der includes.hpp erstmal nichts verändert. Das mache ich, wenn der Code funktioniert.



  • Blu-Ray schrieb:

    und dein includes.hpp ist schlechter Stil

    Soll ich stattdessen die Files einzeln includen?

    Normalerweise inkludiert man in einer Datei genau die Header, die für das Compilieren nötig sind (Dient auch ein wenig der Dokumentation). Zudem sollte man niemals using namespace in einen Header verwenden. Im Zusammenspiel mit Precompiled Headern mag es sinnvoll sein gewisse Header Projektweit zu inkludieren, dies ist aber nicht der Regelfall und sollte einzeln genau überlegt sein.

    Und zu guter letzt: "#include <string.h>" dient nicht dem Include der C++ Klasse std::string, entweder meinst du "#include <string>" [std::string] oder "#include <cstring>" [Für die C-Funktionen zu strings].



  • Ich habe jetzt statt

    #include <string.h>
    

    folgendes verwendet (für std::string)

    #include <string>
    

    Sollte ich jeden String als std::string deklarieren, wenn kein using namespace std verwendet werden soll?



  • Blu-Ray schrieb:

    Sollte ich jeden String als std::string deklarieren, wenn kein using namespace std verwendet werden soll?

    Würde ich machen, besonders im Header. Ist es für dich sehr schlimm, wenn noch ein Namensraumqualifizierer vorne dran steht?



  • Also ich habe std:: jetzt vor cout und vor alle string Deklarationen geschrieben.

    Vielen Dank bis hierher für das Aufräumen des Codes 😃
    Allerdings besteht der Fehler

    D:\workspace\test\katze.hpp|6|error: expected class-name before '{' token|
    

    Durch die Verwendung von der Klasse Tier in der katze.hpp bekomme ich nun zusätzlich folgenden Fehler:

    D:\workspace\test\katze.hpp|9|error: `Tier' does not name a type
    

    obwohl die tier.hpp ja eigentlich mit inkludiert wird


  • Administrator

    Zeig mal, wie du aktuell die Inkludes hast. Denn wie du es vorhin hattest, da wurde schlussendlich die Klasse Katze vor der Klasse Tier deklariert, was natürlich zu einem Fehler führte.

    Grüssli



  • Es wäre es auch nicht verkehrt sich mal mit dem Thema const-correctness auseinander zu setzen (a. Du kopierst ständig strings, wo es nicht nötig wäre und b. nicht-modifizierende Zugriffe (wie getter) sollten const sein).



  • asc schrieb:

    (a. Du kopierst ständig strings, wo es nicht nötig wäre und b. nicht-modifizierende Zugriffe (wie getter) sollten const sein).

    Sonst übergebe ich Parameter auch über Referenzen, allerdings wollte ich dieses Beispiel so einfach wie möglich halten.

    An der Include-File habe ich nichts verändert. Die ist immernoch:

    #include <iostream>
    #include <string>
    
    #include "tier.hpp"
    #include "katze.hpp"
    

    Eigentlich wird die Klasse Tier ja vor der Klasse Katze eingefügt und wird von jeder Datei inkludiert



  • Ist dir eigentlich mal aufgefallen, dass tier.hpp die Datei includes.hpp einbindet, welche die Datei tier.hpp einbindet?

    [Edit] Nicht, dass das zum Fehler führen würde. Schön ist aber was anderes.

    [Edit] Ach doch, tuts. In main.cpp inkludierst du includes.hpp, was wiederum tier.hpp inkludiert. tier.hpp inkludiert wiederum tier.hpp (ohne Auswirkung) und dann katze.hpp. katze.hpp inkludiert nix mehr. Somit steht die Klasse Katze über der Klasse Tier.

    Wie Dravere es wohl auch schon rausgefunden und ich überlesen hab 🤡

    Ich habe an der includes.hpp erstmal nichts verändert. Das mache ich, wenn der Code funktioniert.

    Mach sowas am besten direkt weg, wenn wir dich darauf hinweisen. Denn ein solches include-Gewurstel kann ganz schön kompliziert werden.



  • Hör überhaupt mit zentralen Headerdateien auf. Auch sowas ist unnötig:

    #include "tier.hpp"  // <--
    #include "katze.hpp"
    

    Wenn Tier eine Basisklasse von Katze ist, muss die Tier -Klassendefinition im "katze.hpp" -Header automatisch bekannt sein. Inkludiere "tier.hpp" also dort.

    Ach ja, und verwende keine Bezeichner, die mit Unterstrichen anfangen oder zwei Unterstriche enthalten, da diese für Compiler und Implementierung reserviert sind (das betrifft die Include-Guards).


Anmelden zum Antworten