Verständnisproblem Klassen in C++
-
also ich habe es gerade ausprobiert - klappt nicht.
--------------------Configuration: nn - Debug--------------------
Compiling source file(s)...
main.cpp
inventory.cpp
inventory.cpp:1: error: syntax error before::' token inventory.cpp:7: error: syntax error before<=' token
inventory.cpp:7: error: syntax error before `++' token
inventory.cpp:12:2: warning: no newline at end of filenn.exe - 3 error(s), 1 warning(s)
relevanter source in main:
#include <iostream> #include <windows.h> #include <string> #include <vector> #include "item.h" #include "etc_item.h" #include "weapon.h" #include "armor.h" #include "inventory.h"relevanter source in inventory.h:
#ifndef INVENTORY_H #define INVENTORY_H #include <iostream> #include <windows.h> #include <string> #include <vector> #include "item.h" #include "etc_item.h" #include "weapon.h" #include "armor.h" class inventory {komplette inventory.cpp:
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; }; } }
Ich verstehe nicht, was in Zeile 1 hier falsch sein soll...
-
bololo77 schrieb:
Wenn das stimmt, dann ist die #include Anweisung nicht einfach ein Sourcecode-Platzhalter der beim Kompilieren einfach den entsprechenden Sourcecode an die Stelle setzt wo die #include Anweisung ist?
Und wenn ja, dauert das Compilieren dann nicht ewig länger, da für jede einzelne Klasse diverse Bibliotheken doppelt und dreifach inkludiert werden müssen?
Ja, ist so, und es dauert auch länger. Dafür gibt es dann vorkompilierte Header.
Wegen deinen Fehlern:
Zeig mal die ganze inventory.h. Evtl. das Semikolon nach der Klassendefinition vergessen?
-
Ich sagte: Wenn er xyz.cpp bearbeitet, interessiert ihn nicht was in main.cpp steht.
Wieso wird deshalb doppelt und dreifach includet? Es wird in main.cpp einmal includet und es wird in xyz.cpp einmal includet. Beides ist erforderlich damit er in beiden Dateien die Deklarationen kennt.
Du kompilierst die Files doch unabhängig, wie soll ein include in main.cpp Auswirkungen auf andere Compile-Einheiten haben?
-
#ifndef INVENTORY_H #define INVENTORY_H 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); }; #endifNeku, also hier ist die komplette inventory.h
Lord Jaxoms Ausführungen verstehe ich leider nicht... So wie ich es verstehe muss ich die strings, iostream, vektor etc.p.p in _jeder_ meiner .h Dateien includieren, da ich die dort brauche. Und ich hab ja nicht nur die main und die inventory. Das sind jetzt schon 10 und es werden noch viel viel mehr.
Das meinte ich mit doppelt und dreifach.Naja, ich denke ich packs wieder alles in die main.cpp - Dann hab ich gar keine Probleme mehr und alles wird nur einmal ge-includet, und ich habe keine Syntax Errors mehr (wirklich identisch:copy and paste ohne die includeguards, und die Errors sind weg) .

Gruss
R
-
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); }; #endifbringt 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 ManualIch 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.