Verständnisproblem Klassen in C++



  • Ich habe auch ein Projekt mit ca. 380 cpp/hpp-Dateien. Dann dauert das komplette Kompilieren halt eine Weile, und? Bei Visual Studio werden doch normalerweise ohnehin nur geänderte Source-Dateien kompiliert.
    Wenn ich das alles in eine Datei packe wird's übel 😛

    Den Grund für die Syntaxfehler sehe ich jetzt nicht. Sind es immernoch die gleichen Fehler, wenn du in der inventory.cpp die Includes auskommentierst?

    PS: Es gibt hier einen C++-Highlighter 😉 [cpp][/cpp]



  • Es macht keinen Unterschied.
    Ob ich

    #include <iostream>
    #include <windows.h>
    #include <string>
    #include <vector>
    #include "item.h"
    #include "etc_item.h"
    #include "weapon.h"
    #include "armor.h"
    

    in die .h oder die .cpp schreibe immer das gleiche. Und auch bei allen Klassen wo ich es versucht hab.

    packe ich es in beide (also .cpp und .h) dann bekomme ich >200 Errors.
    Naja, dafür das ich erst ein paar Tage C++ lerne, bin ich ja schon weit gekommen. 🙂

    Ich denke mir fehlt da einfach einiges an Grundverständnis der Sprache...

    Gruss
    R.



  • bololo77 schrieb:

    Es macht keinen Unterschied.
    Ob ich

    #include <iostream>
    #include <windows.h>
    #include <string>
    #include <vector>
    #include "item.h"
    #include "etc_item.h"
    #include "weapon.h"
    #include "armor.h"
    

    in die .h oder die .cpp schreibe immer das gleiche. Und auch bei allen Klassen wo ich es versucht hab.

    packe ich es in beide (also .cpp und .h) dann bekomme ich >200 Errors.
    Naja, dafür das ich erst ein paar Tage C++ lerne, bin ich ja schon weit gekommen. 🙂

    Ich denke mir fehlt da einfach einiges an Grundverständnis der Sprache...

    Gruss
    R.

    Ich schrieb "auskommentieren" 😉 (und zwar die Includes in der .cpp)



  • Erstmal vielen Dank für dein Verständnis einem blutigen Anfänger gegenüber.

    Also die 3 Syntaxfehler von eben kommen wenn ich die include-Anweisungen weder in der inventory.cpp noch in der inventory.h habe.
    Die gleichen Fehler kommen auch wenn ich die include-Anweisungen entweder in der .h ODER in der .cpp habe. Habe ich die includes in _beiden_ kommen >200 Fehler.

    Gruss
    R



  • Tut mir leid, bei den paar Zeilen Code in deiner .cpp kann ich mir die Fehler nicht erklären. Was ist das eigentlich für ein Compiler und für eine IDE?



  • hey hast du die "inventory.h" auch in die "inventory.cpp" includet?
    das sah nämlich nicht so aus...



  • Ich bat ihn ja darum, die Includes in der .cpp zu entfernen, um zu sehen, ob die Syntaxfehler die Schuld der Includes sind oder nicht. Offensichtlich sind sie es nicht.



  • Vielleicht nochmal was zum Vorgehen generell, vielleicht wird es dann etwas klarer für den blutigen Anfänger 😉

    Wenn Du Klassen bastelst, bei der die Trennung erfolgen soll, solltest Du alles in die .h includen, was in der .h auch gebraucht wird. Deklarierst Du in der Klasse ein std::string name, dann includest Du <string>. Bei einem vector<weapon> includest Du <vector> sowie Deine .h für die Klasse weapon. (Wenn Du weiter Fortgeschritten bist kannst Du etwas davon einsparen durch Forward Deklaration, aber da denk besser noch nicht drüber nach)

    Natürlich kannst Du das auch erschlagen, indem Du die benötigten Header alle zuvor in der .cpp includest, aber das ist sehr schlechter Stil, denn ich (hypothetisch natürlich) als Anwender Deiner Klassen möchte nicht dafür sorgen müssen die Header zu includen, die Du brauchst.

    Header, die in der Klassendeklaration nicht gebraucht werden, sondern erst im Code der Klasse in der .cpp-Datei, solltest Du natürlich erst in der .cpp-Datei includen. Damit ersparst Du dem Anwender, der nur die .h includet und später eine fertige Bibliothek linkt, und letztlich Dir selbst Symboltabellenverschmutzung (und Compilierungszeit).

    Also, geh Deine Header mal in Ruhe durch und include in ihnen alles was auch im Header benutzt wird. Dann das gleiche für die Sourcefiles. Mach Dir keine Sorgen über doppelte Includes, wenn Du also in Deiner .cpp-Datei "weapon.h" includest, und neue Vectoren nutzt, verlasse Dich nicht auf die Tatsache dass "weapons.h" <vector> includet, include <vector> lieber selbst in der .cpp noch mal.

    Kleines Beispiel anhand der Inventory-Klasse.

    /* inventory.h */
    #ifndef INVENTORY_H
    #define INVENTORY_H
    
    #include <vector>
    #include "etc_item.h" // Die Datei in der Deine Klasse etc_item enthalten ist
    #include "weapon.h" // Die Datei in der Deine Klasse weapon enthalten ist
    
    class inventory
        {
        public:
        std::vector<etc_item> etc_items;
        std::vector<weapon> weapons;
        inventory(){}   //konstruktor
        unsigned int weight();
        bool isfull();
        void stats();
        short int add_etc (unsigned long itid, unsigned short int how_much);   
        bool has_etc(unsigned long itid, unsigned short int how_much);
        bool remove_etc(unsigned long itid, unsigned short int how_much);
    };
    #endif
    
    /* inventory.cpp */
    #include "inventory.h" // Ich brauche die Klasse, um ihre Methoden implementieren zu können
    #include <string> // Irgendwo in diesen Methoden benutze ich string
    
    /* Die Methoden */
    


  • Mach mal hinter die geschweiften Klammern des Konstruktors ein Semikolon...



  • Wozu?



  • Wenigstens damit der unregistrierte Feigling Ruhe gibt 😛



  • hallo nochmal,

    also die folgende inventory.cpp

    #include <iostream>
    #include "etc_item.h"
    
    void inventory::stats()
    {
        //etc_items :
        if (etc_items.size()==0) {cout<<"Nixdrin"<<endl;}
        else
        {
        for(unsigned int i=0;i<=etc_items.size()-1;i++)  //search for existence of the stackable item
        {
            cout<<etc_items[i].amount<<" Einheiten der ID "<<etc_items[i].etc_item_id<<endl;
        };
        }
    }
    

    in Kombination mit der folgenden inventory.h

    #ifndef INVENTORY_H
    #define INVENTORY_H
    #include <vector>
    #include "etc_item.h" // Die Datei in der Deine Klasse etc_item enthalten ist
    #include "weapon.h" // Die Datei in der Deine Klasse weapon enthalten ist
    
    class inventory
    	{
    	public:
    	//hier müssen die 3 vektoren für etc, armor und weapons rein.
    	std::vector<etc_item> etc_items;
    	//std::vector<weapon> weapons;
    	//std::vector<armor> armors;
    
    	inventory(){}; //semikolon eingefügt
    	unsigned int weight();	
    	//int add_armor (unsigned long itid);
    	int add_weapon (unsigned long itid);	
    
    	//int has_etc has_weapon has_armor (unsigned long itid, unsigned short int how_much); 
    	//int remove_etc remove_weapon remove_armor (unsigned long itid, unsigned short int how_much);
    	//exchangeorder (slotx, sloty)
    	bool isfull();
    	void stats();
    	short int add_etc (unsigned long itid, unsigned short int how_much);
    	bool has_etc(unsigned long itid, unsigned short int how_much);
    	bool remove_etc(unsigned long itid, unsigned short int how_much);
    };
    #endif
    

    bringt nun folgenden Fehler:

    --------------------Configuration: nn - Debug--------------------
    Compiling source file(s)...
    inventory.cpp
    inventory.cpp:5: error: syntax error before `::' token
    inventory.cpp:11: error: syntax error before `<=' token
    inventory.cpp:11: error: syntax error before `++' token
    nn.exe - 3 error(s), 0 warning(s)
    

    Der Compiler den ich benutze ist der vom MinGW developer Studio 2.05.

    MinGWStudioFullSetup-2.05.exe (26,633,338)
    - Files in packkage No. 1.
    - MinGW Developer Studio files
    - MinGW(C/C++ only) Compiler 3.4.2
    - Binutils 2.15.94
    - Windows32 API 3.2
    - MinGW Runtime Lirbraries 3.7
    - GNU Debugger(GDB) 6.0
    - GNU Make 3.80.0-3
    - Windows API Reference Manual

    Ich kann natürlich den kompletten Sourcecode posten, aber ich denke keiner hat Lust in seiner Freizeit an die 1000 Codezeilen durchzulesen...
    Daher hab ich versucht mich an auf die wesentlichen Stellen zu beschränken.
    😞 Also langsam beginne ich mich an den Gedanken zu gewöhnen, die Klassendefinitionen in .h Dateien auszulagern und die Methoden halt in der main.cpp zu haben.

    Vielleicht ist es nicht so wichtig, aber ich erwähne es doch mal explizit.
    Die Klassen, die ich habe bauen aufeinander auf. Sprich es gibt eine Urklasse, von der sich alles ableitet: item.h Da ist nicht viel drin, aber etc_item.h, armor.h und weapon.h sind Tochterklassen der Art "class etc_item : public item".
    Diese drei abgeleiteten benutze ich in einer neuen Klasse inventory.h ohne dass ich der inventory.h sage, dass etc_item von item abhängt. (in der etc_item.h ist natürlich die item.h inkludiert)... Vielleicht liegts ja daran?



  • In meinem Beispiel ist inventory.h in inventory.cpp eingebunden, bei Dir nicht!

    Der Compiler muss doch beim Auftauchen von inventory::stats wissen dass inventory eine Klasse ist, das kann er nur dann...



  • Es geht aber um Syntaxfehler, nicht um unbekannte Klassenbezeichner.

    @bololo: Ersetz mal alle "short int" durch "short". "short int" habe ich noch nie gesehen 😕



  • 5: error: syntax error before `::' token

    Vor :: in dieser Zeile steht der Klassenname inventory, deshalb denke ich schon dass das darauf zurückzuführen ist dass der Header noch fehlt.

    Aber was auch für typische Verwirrungsfehler sorgt, schau mal in der etc_item.h ob die Klasse korrekt mit }; abgeschlossen ist...



  • Vielleicht reagiert speziell dieser Compiler auf fehlende Bezeichner mit Syntaxfehlern, was aber bescheuert wäre.



  • Hallo,

    nachdem ich nun alles was ich hab in der inventory.cpp inkludiere, bekomme ich nun andere Fehler beim compilieren. So wie ich im ersten posting geschrieben hab, funktionieren plötzlich Sachen wie cout nciht mehr, obwohl ich die iostream inkludiere...

    --------------------Configuration: nn - Debug--------------------
    Compiling source file(s)...
    inventory.cpp
    inventory.cpp: In member function `void inventory::stats()':
    inventory.cpp:14: error: `cout' undeclared (first use this function)
    inventory.cpp:14: error: (Each undeclared identifier is reported only once for
    each function it appears in.)
    inventory.cpp:14: error: `endl' undeclared (first use this function)
    
    nn.exe - 3 error(s), 0 warning(s)
    

    inventory.h:

    #include <iostream>
    #include <windows.h>
    #include <vector>
    #include "item.h"
    #include "etc_item.h" // Die Datei in der Deine Klasse etc_item enthalten ist
    #include "weapon.h" // Die Datei in der Deine Klasse weapon enthalten ist
    #include "armor.h"
    #include "inventory.h"
    
    void inventory::stats()
    {
        //etc_items :
        if (etc_items.size()==0) {cout<<"Nixdrin"<<endl;}
        else
        {
        for(unsigned int i=0;i<=etc_items.size()-1;i++)  //search for existence of the stackable item
        {
            cout<<etc_items[i].amount<<" Einheiten der ID "<<etc_items[i].etc_item_id<<endl;
        };
        }
    }
    

    inventory.h:

    #ifndef INVENTORY_H
    #define INVENTORY_H
    #include <iostream>
    #include <vector>
    #include <windows.h>
    #include "etc_item.h" // Die Datei in der Deine Klasse etc_item enthalten ist
    #include "weapon.h" // Die Datei in der Deine Klasse weapon enthalten ist
    #include "armor.h"
    #include "item.h"
    
    class inventory
    	{
    	public:
    	//hier müssen die 3 vektoren für etc, armor und weapons rein.
    	std::vector<etc_item> etc_items;
    	std::vector<weapon> weapons;
    	//std::vector<armor> armors;
    
    	inventory(){};
    	unsigned int weight();	
    	//int add_armor (unsigned long itid);
    	short add_weapon (unsigned long itid);	
    
    	//int has_etc has_weapon has_armor (unsigned long itid, unsigned short how_much); 
    	//int remove_etc remove_weapon remove_armor (unsigned long itid, unsigned short how_much);
    	//exchangeorder (slotx, sloty)
    	bool isfull();
    	void stats();
    	short add_etc (unsigned long itid, unsigned short how_much);
    	bool has_etc(unsigned long itid, unsigned short how_much);
    	bool remove_etc(unsigned long itid, unsigned short how_much);
    };
    #endif
    

    Alle Klassendefinitionen in den .h Dateien sind mit }; abgeschlossen. (vor dem #endif)

    Die Tatsache, dass ich jetzt ein bischen hartnäckig versuche das auszulagern ist die, dass wenn ich es nicht jetzt am Anfang mache, mache ich es wohl nie...

    Ich hoffe ihr versteht das.

    Gruss
    R



  • In der inventory.cpp sind die meisten Header nun unnötig, da du sie in der inventory.h bereits einbezogen hast.

    *edit*
    Versuch mal "std::cout << ... << std::endl;" bzw. nach den #includes: "using namespace std;".



  • Wahnsinn, es läuft! 🕶 🕶 🕶

    👍 Ein aufrichtiges Danke an alle die sich so aktiv hier beteiligt haben. 👍
    Ihr wisst ja nicht wie sehr ich hier verzweifelt war.
    Jetzt kann ich successive bibliotheken herausnehmen die ich nicht brauche.

    bololo77 schrieb:

    Ich bin so ratlos, dass ich noch nichtmal weiß wo und über welches Thema ich nachlesen muss. (Vielleicht Namespaces?)

    Hatte ja schon in diese Richtung gedacht, aber die Syntax errors haben mich mehr verwirrt als irgendwelche Namespaces.

    C++ ist doch ganz anders als Delphi (welches ich bisher benutzte) und C, welches ich mal vor 10 Jahren mir mal etwas genauer anschaute.

    Ich hoffe ich darf weitere Fragen auf die ich selber keine Antwort ergooglen kann weiterhin hier posten...

    Super, mein Abend ist gerettet!

    Gruss+Dank
    Robin



  • Jetzt habe ich dann doch noch eine Frage...
    Kann ich die Konstruktoren einer Klasse (die teilweise langen Sourcecode haben), deren Definition z.Z in einer .h - Datei sind in die .cpp Dateien auslagern?

    Meine Versuche brachten immer den Fehler:

    --------------------Configuration: nn - Debug--------------------
    Compiling source file(s)...
    main.cpp
    In file included from main.cpp:6:
    etc_item.h:15: error: function body for constructor missing
    main.cpp:12: error: syntax error before `namespace'
    main.cpp:47: error: syntax error at end of input
    nn.exe - 3 error(s), 0 warning(s)
    

    Oder anders gefragt, gibt es im Netz ein Tutorial, welches sich ausgiebig mit diesem Thema auseinandersetzt?
    Ich bin ja lernwillig. 🙂


Anmelden zum Antworten