Klasse nicht korrekt eingebunden
-
Hi,
das ist jetzt schon das zweite Mal heute, dass ich mich hier melde. ist mir schon richtig peinlich, aber ich finde einfach keinen Fehler.Meine Fehlermeldung ist:
In file included from GLSystem/GLSystem.h:23, from main.cpp:15: GLSystem/GLFlatAnimObject.h: At global scope: GLSystem/GLFlatAnimObject.h:52: error: ISO C++ forbids declaration of ‘GLTexture’ with no type GLSystem/GLFlatAnimObject.h:52: error: expected ‘;’ before ‘*’ tokenIch habe GLTexture.h in der GLSystem extra nach oben verschoben, aber es hat nicht gegen den Fehler geholfen.
GLSystem.h
#ifndef GL_SYSTEM #define GL_SYSTEM #include "GLWindow.h" #include "GLObject.h" #include "GLTexture.h" #include "GLFlatObject.h" //#include "GLVolObject.h" #include "GLTime.h" #include "GLInput.h" #include "GLAudio.h" #include "GLSound.h" #include "GLMusic.h" #include "GLBitFont.h" #include "GLText.h" #include "GLCam.h" #include "GLCursor.h" #include "GLInfo.h" #include "GLChannel.h" #include "GLKeyRepeat.h" #include "GLStopper.h" #include "GLNet.h" #include "GLFlatAnimObject.h" #include "GLAnimCursor.h" #include "GLFlatCursor.h" #include "GLPacket.h" #include "GLBlockedID.h" #include "GLMouseObject.h" #endifGLFlatAnimObject.h
#ifndef GL_FLATANIMOBJECT #define GL_FLATANIMOBJECT #include <string> #define LINUX #ifdef LINUX #include <SDL/SDL_video.h> #include <SDL/SDL_opengl.h> #else #include <SDL_video.h> #include <SDL_opengl.h> #endif #include "GLTime.h" #include "GLObject.h" #include "GLCam.h" #include "GLTexture.h" class GLFlatAnimObject : public GLObject { public: GLFlatAnimObject(GLTime* time, GLCam* camera); //etc. private: //etc. GLTexture* First; GLCam* Camera; }; #endifVorwärtsdeklaration mit "class GLTexture;" hat auch nicht gegen den Fehler geholfen. Dann habe ich nur noch zusätzlich in GLFlatAnimObject.cpp Fehler erhalten, weil dort die Klasse GLTexture auch unbekannt war.
Findet jemand einen Fehler? Danke für's anschauen.

-
Little Programmer schrieb:
Ich habe GLTexture.h in der GLSystem extra nach oben verschoben, aber es hat nicht gegen den Fehler geholfen.
Wenn du auch nur vermutest, dass die Reihenfolge von Includes Auswirkung auf das Verhalten deiner Header haben könnte, dann liegt schon etwas im Argen. Schreibe deine Header immer so, dass sie auf jeden Fall für sich alleine stehen können. Mach nichts unnötiges rein (Für einen Pointer reicht eine Vorwärtsdeklaration) aber lass auch nichts weg.
-
Mit der Vorwärtsdeklaration erhalte ich für jeden Zugriff auf den Zeiger in GLFlatObject.cpp folgende Fehlermeldung:
GLSystem/GLFlatAnimObject.cpp: In destructor ‘virtual GLFlatAnimObject::~GLFlatAnimObject()’: GLSystem/GLFlatAnimObject.cpp:71: error: invalid use of incomplete type ‘struct GLTexture’ GLSystem/GLFlatAnimObject.h:17: error: forward declaration of ‘struct GLTexture’ GLSystem/GLFlatAnimObject.cpp: In member function ‘bool GLFlatAnimObject::load(const std::string&, int, bool)’: GLSystem/GLFlatAnimObject.cpp:80: error: invalid use of incomplete type ‘struct GLTexture’ GLSystem/GLFlatAnimObject.h:17: error: forward declaration of ‘struct GLTexture’ GLSystem/GLFlatAnimObject.cpp:94: error: invalid use of incomplete type ‘struct GLTexture’ //etc.obwohl ich die Header in der cpp inkludiere.
Hier nochmal GLFlatAnimObject.h
#include <string> #define LINUX #ifdef LINUX #include <SDL/SDL_video.h> #include <SDL/SDL_opengl.h> #else #include <SDL_video.h> #include <SDL_opengl.h> #endif #include "GLTime.h" #include "GLObject.h" class GLCam; class GLTexture; class GLFlatAnimObject : public GLObject { public: //etc.und hier die GLFlatAnimObject.cpp:
#include "GLFlatAnimObject.h" #include "GLObject.h" #include "GLTime.h" #include "GLTexture.h" #include "GLCam.h" #define LINUX #ifdef LINUX #include <SDL/SDL.h> #include <SDL/SDL_opengl.h> #include <SDL/SDL_image.h> #include <unistd.h> //Um Pfad zum eigenen Ordner beim Dateiladen zu ermitteln #else #include <SDL.h> #include <SDL_opengl.h> #include <SDL_image.h> #endif #include <string> #include <sstream> GLFlatAnimObject::GLFlatAnimObject(GLTime* time, GLCam* camera) : GLObject(time), W(0), H(0), Frames(0), CurrFrame(0), Loop(false), Starttime(-1), Texture(0), First(0), Camera(camera) {} //etc.Und was kann ich jetzt noch probieren?
-
Hier das Ergebnis, wenn ich die Headerdateien für GLCam.h und GLTexture.h in GLFlatAnimObject.h inkludiere. Dabei ist es egal, ob ich sie in GLFlatAnimObject.cpp nochmal inkludiere oder nicht. Hab auch schon mehrmals alle Objektdateien gelöscht und das Projekt komplett neu kompiliert. Aber die Fehlermeldung bleibt gleich.
In file included from GLSystem/GLFlatAnimObject.cpp:1: GLSystem/GLFlatAnimObject.h:55: error: ISO C++ forbids declaration of ‘GLTexture’ with no type GLSystem/GLFlatAnimObject.h:55: error: expected ‘;’ before ‘*’ token GLSystem/GLFlatAnimObject.cpp: In constructor ‘GLFlatAnimObject::GLFlatAnimObject(GLTime*, GLCam*)’: GLSystem/GLFlatAnimObject.cpp:21: error: class ‘GLFlatAnimObject’ does not have any field named ‘First’
-
Ich würde einfach mal vermuten, dass du da eben irgendwo zirkuläre #includes hast, also Header die sich direkt oder indirekt gegenseitig inkludieren. Zusammen mit Includeguards führt das dann genau zu solchen Fehlern...
-
Dann hast du vielleicht einen Fehler bei der Deklaration von GLTexture.
-
GLTexture.h habe ich neu geschrieben, es wird momentan nur von der Klasse GLFlatAnimObject verwendet, also auch von keiner anderen Klasse inkludiert. Lediglich main.cpp inkludiert mit GLSystem.h alle Header-Dateien.
GLFlatAnimObject.h beginnt so, es führt nur eine Vorwärtsdeklaration der Klasse GLTexture durch, inkludiert sie aber nicht:
#ifndef GL_FLATANIMOBJECT #define GL_FLATANIMOBJECT #include <string> #define LINUX #ifdef LINUX #include <SDL/SDL_video.h> #include <SDL/SDL_opengl.h> #else #include <SDL_video.h> #include <SDL_opengl.h> #endif #include "GLTime.h" #include "GLObject.h" class GLCam; class GLTexture; class GLFlatAnimObject : public GLObject {GLFlatAnimObject.cpp inkludiert sie dann schließlich:
#include "GLFlatAnimObject.h" #include "GLObject.h" #include "GLTime.h" #include "GLTexture.h" #include "GLCam.h" #define LINUX #ifdef LINUX #include <SDL/SDL.h> #include <SDL/SDL_opengl.h> #include <SDL/SDL_image.h> #include <unistd.h> //Um Pfad zum eigenen Ordner beim Dateiladen zu ermitteln #else #include <SDL.h> #include <SDL_opengl.h> #include <SDL_image.h> #endif #include <string> #include <sstream> GLFlatAnimObject::GLFlatAnimObject(GLTime* time, GLCam* camera) : GLObject(time), W(0), H(0), Frames(0), CurrFrame(0), Loop(false), Starttime(-1), Texture(0), First(0), Camera(camera) {}Die Datei GLTexture.h ist klein, die kann ich komplett hier rein kopieren. Sie bindet aber keine andere Datei aus dem Projekt ein, also kann dort eigentlich kein Fehler liegen.
#ifndef GL_TEXTURE #define GL_TEXTURE #include <string> #define LINUX #ifdef LINUX #include <SDL/SDL_opengl.h> #include <SDL/SDL_image.h> #else #include <SDL_opengl.h> #include <SDL_image.h> #endif class GLTexture { public: GLTexture(const std::string& filename) : Next(0), Texture(0) { load(filename); } ~GLTexture() {glDeleteTextures(1, &Texture);} //Bild aus Datei laden bool load(const std::string& filename) { glDeleteTextures(1, &Texture); //Eventuell alte Textur löschen SDL_Surface* surface = IMG_Load(filename.c_str()); if(!surface) return false; glPixelStorei(GL_UNPACK_ALIGNMENT,4); glGenTextures(1, &Texture); glBindTexture(GL_TEXTURE_2D, Texture); SDL_PixelFormat *format = surface->format; if(format->Amask) { gluBuild2DMipmaps(GL_TEXTURE_2D, 4, surface->w, surface->h, GL_RGBA,GL_UNSIGNED_BYTE, surface->pixels); } else { gluBuild2DMipmaps(GL_TEXTURE_2D, 3, surface->w, surface->h, GL_RGB, GL_UNSIGNED_BYTE, surface->pixels); } SDL_FreeSurface(surface); //Lineare Filterung für Groß- und Kleinzoomen von Textur aktivieren glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); //Texturmapping allgemein aktivieren glEnable(GL_TEXTURE_2D); return true; } void setNext(GLTexture* next) {Next = next;} GLTexture* getNext() {return Next;} GLuint* getTexture() {return &Texture;} void deleteall() {if(Next != 0) {Next->deleteall(); delete Next;}} private: GLTexture* Next; GLuint Texture; }; #endifUnd zur Übersicht, damit es komplett ist, die GLSystem.h, welche in main.cpp alle Klassen auf einmal einbindet:
#ifndef GL_SYSTEM #define GL_SYSTEM #include "GLWindow.h" #include "GLObject.h" #include "GLTexture.h" #include "GLFlatObject.h" //#include "GLVolObject.h" #include "GLTime.h" #include "GLInput.h" #include "GLAudio.h" #include "GLSound.h" #include "GLMusic.h" #include "GLBitFont.h" #include "GLText.h" #include "GLCam.h" #include "GLCursor.h" #include "GLInfo.h" #include "GLChannel.h" #include "GLKeyRepeat.h" #include "GLStopper.h" #include "GLNet.h" #include "GLFlatAnimObject.h" #include "GLAnimCursor.h" #include "GLFlatCursor.h" #include "GLPacket.h" #include "GLBlockedID.h" #include "GLMouseObject.h" #endifIch sehe jetzt nirgends einen Fehler, wo sich etwas gegenseitig inkludieren würde o.ä.
-
Dein Compiler wird gewiss auch die Option bieten, den Preprocessoroutput anzuzeigen. Da kannst du mal gucken, ob wirklich alles in der Reihenfolge vorkommt, wie du denkst.
-
Das Resultat:
g++ -E -c -Wall main.cpp -o main.o g++ -E -c -Wall GLSystem/GLFlatObject.cpp -o GLSystem/GLFlatObject.o g++ -E -c -Wall GLSystem/GLObject.cpp -o GLSystem/GLObject.o g++ -E -c -Wall GLSystem/GLTime.cpp -o GLSystem/GLTime.o g++ -E -c -Wall GLSystem/GLWindow.cpp -o GLSystem/GLWindow.o g++ -E -c -Wall GLSystem/GLInput.cpp -o GLSystem/GLInput.o g++ -E -c -Wall GLSystem/GLAudio.cpp -o GLSystem/GLAudio.o g++ -E -c -Wall GLSystem/GLSound.cpp -o GLSystem/GLSound.o g++ -E -c -Wall GLSystem/GLMusic.cpp -o GLSystem/GLMusic.o g++ -E -c -Wall GLSystem/GLBitFont.cpp -o GLSystem/GLBitFont.o g++ -E -c -Wall GLSystem/GLText.cpp -o GLSystem/GLText.o g++ -E -c -Wall GLSystem/GLCam.cpp -o GLSystem/GLCam.o g++ -E -c -Wall GLSystem/GLCursor.cpp -o GLSystem/GLCursor.o g++ -E -c -Wall GLSystem/GLInfo.cpp -o GLSystem/GLInfo.o g++ -E -c -Wall GLSystem/GLNet.cpp -o GLSystem/GLNet.o g++ -E -c -Wall GLSystem/GLFlatAnimObject.cpp -o GLSystem/GLFlatAnimObject.o g++ -E -c -Wall GLSystem/GLAnimCursor.cpp -o GLSystem/GLAnimCursor.o g++ -E -c -Wall GLSystem/GLFlatCursor.cpp -o GLSystem/GLFlatCursor.o g++ -E -c -Wall GLSystem/GLMouseObject.cpp -o GLSystem/GLMouseObject.o g++ -lSDL -lGL -lSDL_image -lGLU -lSDL_mixer -lSDL_net main.o ./GLSystem/GLFlatObject.o ./GLSystem/GLObject.o ./GLSystem/GLTime.o ./GLSystem/GLWindow.o ./GLSystem/GLInput.o ./GLSystem/GLAudio.o ./GLSystem/GLSound.o ./GLSystem/GLMusic.o ./GLSystem/GLBitFont.o ./GLSystem/GLText.o ./GLSystem/GLCam.o ./GLSystem/GLCursor.o ./GLSystem/GLInfo.o ./GLSystem/GLNet.o ./GLSystem/GLFlatAnimObject.o ./GLSystem/GLAnimCursor.o ./GLSystem/GLFlatCursor.o ./GLSystem/GLMouseObject.o -o 2DTest main.o: file not recognized: File format not recognized collect2: ld returned 1 exit status make: *** [2DTest] Fehler 1Erscheint mir jetzt zufällig die Reihenfolge. Hat auch nichts damit zu tun, in welcher Reihenfolge ich Objekte der Klassen in main.cpp erstelle, die ist anders.
-
Ich kopiere jetzt das gesamte Projekt und lösche alle inkludes aus der Kopie heraus. Dann inkludiere und "vorwärtsdeklariere" ich alles neu. Vielleicht ist der Fehler irgendwi versteckt und verschwindet dann. Ich hoffe nur es werden nicht mehr Fehler^^.
-
So war das mit dem Präprozessorcode nicht gemeint. Du sollst ihn dir anzeigen und durchlesen (beziehungsweise nach der Position der Schlüsselstellen zueinander suchen).
-
Man wirds nicht glauben. Obwohl ich einiges geändert habe, kompiliert es genauso wie vorher und der Fehler ist auch noch der gleiche wie vorher. Es muss also doch irgendwie mit der Klasse GLTexture zusammen hängen. Sieht denn wirklich niemand einen Fehler?
-
Folge Sepps Rat. Damit hast du gute Chancen. Ansonsten hat glaube ich keiner Lust, sich durch dieses Durcheinander zu wühlen.
-
Anzeigen lassen kann ich ihn mir nicht. Nur aus allen Dateien zusammensuchen.
Zuerst beginnt es in der main.cpp mit dem inkludieren von GLSystem.h. Diese inkludiert in diesem Zusammenhang als erstes GLTexture.h, welches an sich keine weiteren Projektdateien inkludiert. Später wird dann von GLSystem.h GLFlatAnimObject.h inkludiert. Dieses inkludiert GLTime.h und GLObject.h, welche aber, wie auch alle anderen Dateien des Projekts, keine Verbindung zu GLTexture.h haben.
War es das was ihr meint?
-
mach mal
g++ -E main.cpp. Dann wirst du verstehen, was ich meine. Und da das sehr unübersichtlich ist, speicherst du das Ergebnis in einer Datei und suchst mit deinem Lieblingseditor in welcher Zeile GLTexture definiert wird und in welcher Zeile es das erste mal benutzt wirst und dann wirst du ziemlich sicher feststellen, dass letzteres vor ersterem sein wird. Und dann kannst du nachvollziehen, warum dies so ist.
-
So ganz verstehe ich nicht, was die Ausgabe bedeutet. Das erste mal wird GLTexture.h nach dem Quelltext einer anderen Klasse erwähnt. Ich nehme mal an, diese Klasse wurde dort kompiliert. Der Kontext in dem GLTexture.h steht ist folgender:
# 6 "GLSystem/GLSystem.h" 2 # 1 "GLSystem/GLTexture.h" 1 # 7 "GLSystem/GLSystem.h" 2 # 1 "GLSystem/GLFlatObject.h" 1Was genau sagen mir die Zahlen vor und hinter dem Pfad? Und wurde hier die Klasse deklariert oder was genau bedeutet die Erwähnung?
Anschließend steht GLTexture nur noch in der Klasse GLFlatAnimObject.h, welche auch als Quelltext dargestellt ist. Also an dieser Stelle wahrscheinlich kompiliert wurde.
Ich würde jetzt fast annehmen, dass die einfache Erwähnung oben keine Deklarierung darstellt und GLTexture.h nie deklariert wird. Aber ich weiß nicht warum.

-
1. Da wurde gar nichts compiliert. Das ist die Ausgabe des Präprozessors. Das ist das was der Compiler sieht, nachdem der Präprozessor das Spaghettieknäuel deiner Header verwurstet hat. Und daran kannst du dann nachvollziehen, warum der Compiler Probleme mit deinem Code hat.
2. Die Zeilen die du da hin geschrieben hast sind so eine Art "Kommentare" des Präprozessors für den Compiler. Der soll schließlich sinnvolle Meldungen über den Ort der fehlerhaften Zeilen machen können. Da der Präprozessoroutput alles ist, was der Compiler noch sieht, muss ihm die Information über Zeilen und Dateien irgendwie zugesteckt werden. Guckst du hier, wenn dich das interessiert:
http://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html
-
Ok, jetzt habe ich durchgeblickt.
Der Präprozessor geht meine includes in GLSystem.h durch, in dem ja alle anderen Dateien inkludiert werden.
Hier der Abschnitt in GLSystem.h
#include "GLObject.h" #include "GLTexture.h" #include "GLFlatObject.h"Jetzt die Präprozessorausgabe dazu mit Erläuterungen von mir:
# 1 "GLSystem/GLObject.h" 1 //Es wird mit GLObject.h begonnen # 11 "GLSystem/GLObject.h" # 1 "GLSystem/GLTime.h" 1 //Dort ist GLTime.h inkludiert, also wird dies eingeschoben # 11 "GLSystem/GLTime.h" class GLTime { //etc. }; # 12 "GLSystem/GLObject.h" 2 //Es wird mit GLObject.h fortgefahren class GLObject { //etc. }; # 6 "GLSystem/GLSystem.h" 2 //Rückkehr zu GLSystem.h # 1 "GLSystem/GLTexture.h" 1 [b]//Es wird mit GLTexture.h begonnen[/b] # 7 "GLSystem/GLSystem.h" 2 [b]//Rückkehr zu GLSystem.h[/b] # 1 "GLSystem/GLFlatObject.h" 1 //Es wird mit GLFlatObject.h begonnen # 1 "/usr/include/SDL/SDL_opengl.h" 1 3 4 //Inkludierungen in GLFlatObject.h # 64 "/usr/include/SDL/SDL_opengl.h" 3 4 extern "C" { # 3103 "/usr/include/SDL/SDL_opengl.h" 3 4 # 1 "/usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h" 1 3 4 # 3104 "/usr/include/SDL/SDL_opengl.h" 2 3 4 # 6551 "/usr/include/SDL/SDL_opengl.h" 3 4 } # 9 "GLSystem/GLFlatObject.h" 2 //Es wird mit GLFlatObject.h fortgefahren class GLTime; class GLCam; class GLFlatObject : public GLObject { //etc. }; # 8 "GLSystem/GLSystem.h" 2 //Rückkehr zu GLSystem.hWie man sieht, wird GLTexture.h einfach übersprungen. Die einzige Möglichkeit, welche mir dafür einfällt, wäre, dass die Präprozessorabfrage gegen Mehrfacheinbindung fehlschlägt:
#ifndef GL_TEXTURE #define GL_TEXTURE #include <string> #define LINUX #ifdef LINUX #include <SDL/SDL_opengl.h> #include <SDL/SDL_image.h> #else #include <SDL_opengl.h> #include <SDL_image.h> #endif class GLTexture { //etc. }; #endifAber es gibt keine andere Klasse mit gleichem Namen. Woher sollte also GL_TEXTURE kommen?
Ich wurde jetzt nicht schlauer daraus. Hat jemand von euch eine Ahnung, wieso der Präprozessor eine Datei überspringt?
-
Das ist doch genau das was ich gesagt hab: Zirkuläre #includes. Deine Präprozessorabfrage gegen Mehrfacheinbindung schlägt nicht fehl, sie tut genau das, wofür sie gedacht ist: Sie verhindert die Mehrfacheinbindung...
-
Aber das ist die einzige Einbindung von GLTexture.h. Später in GLFlatAnimObject.h ist es, obwohl es inkludiert wird, nicht mehr erwähnt, da hat der Präprozessor es tatsächlich komplett übersprungen. Aber vor dieser Einbindung, welche ich hier gepostet habe, wurde es nicht eingebunden. Die gepostete Stelle ist die einzige Stelle, in der es in der Präprozessorausgabe auftaucht.
-
Beispiel:
A.h inkludiert gleich am Anfang B.h.
B.h braucht Dinge aus A.h und inkludiert daher wieder A.h.
A.h wird nun aber übersprungen, da es schon inkludiert wurde.
D.h. in B.h gibts kein A.h obwohl es eigentlich gebraucht wird. Erst nach B.h kommt der eigentliche Inhalt von A.h, aber dort ist es zu spät.