Verschiedene Compilererror
-
Okay, ich denke ich habe den Fehler gefunden. Zwar kann ich ihn noch nicht lösen, aber vielleicht könnt ihr mir dabei etwas helfen... Also ich habe mal versucht die Datei icMatrix.cpp aus dem Projekt zu entfernen und: Keine Fehler, alles läuft perfekt! Folglich liegt es der Fehler nicht in der Headerdetei icMatrix.h. Dann habe ich die Datei icMatrix.cpp, wieder hinzugefügt und den ganzen Code auskommentiert, bis auf
#include <IonCore.h>und: Alle Fehler wie oben werden wieder angezeigt. Das heißt also, dass deine Vermutung anscheinend richtig ist: Eine Headerdatei ist nicht eingebunden. Ich habe vorher natürlich über Extras -> Optionen... -> Projekte und Projektmappen -> VC++-Verzeichnisse unter Includedateien den Pfad der Datei IonCore.h angegeben. Habe ich vielleicht etwas vergessen?P.S: Ich verstehe deine Kritik und weiß sie auch zu schätzen, aber ich versuche nicht eine ganze Engine (wie bei Profis) zu programmieren, sondern nur ein paar Basisklassen und Funktionen einzubetten. Wenn du sagst, dass die Implementierung von Matrizen nicht sinnvoll ist, dann werde ich mich später nochmal im Spielprogrammierung-Forum informieren, das Problem liegt trotzdem nicht in der Matrixklasse (oder den Funktionen), sondern wahrscheinlich an der Headerdatei die nicht gefunden wird oder so. Deshalb ist es ja erstmal egal was ich reinpacke in die Engine, der Fehler wird überall so sein.
-
Okay, ich will ja nicht drängen, aber hat keiner irgendeine Idee, was ich falsch gemacht haben könnte?
-
1.) #pragma once ist Visual Studio spezifisch und scheisse. Das macht deinen Code inportabel. Vielleicht in dem Fall nicht so schlimm, ich mags trotzdem nicht. Nutze include-guards.
2.) In icMatrix.h verwendest du in Zeile 18 icMatrix bevor die Klasse definiert wird. Schreib die Funktionsdeklaration unter die Klasse.
-
icMatrix.h, Zeile 18:
IONCORE_API icMatrix icMatrixInvert (const icMatrix& m);Was der Compiler zu dem Zeitpunkt nicht kennt:
IONCORE_APundicMatrix.Und dass die Fehler nicht auftreten, wenn icMatrix.cpp aus dem Projekt raus ist, sollte auch klar sein: Dann wird deine icMatrix.h wohl nirgendwo anders verwendet, d.h. vom Compiler auch niemals geparst => Er kann sich also gar nicht beklagen.
-
Scorcher24 schrieb:
1.) #pragma once ist Visual Studio spezifisch
Nein.
Scorcher24 schrieb:
Vielleicht in dem Fall nicht so schlimm, ich mags trotzdem nicht. Nutze include-guards.
Wenn man nicht alle Compiler unterstützen will, kann man das ruhig machen, auch wenn du es nicht magst. Man muss sich nämlich keine Makros ausdenken und gegebenenfalls ändern, hat weniger zu schreiben und der Präprozessorvorgang läuft möglicherweise schneller ab. Auch wenn das keine enormen Vorteile sind.
Viel schlimmer finde ich z.B., dass alles inline ist, dass merkwürdige Operatoren wie / auf Vektoren definiert werden, dass Code nicht wiederverwendet wird und dass durch Zeiger-Umbiegen undefiniertes Verhalten entsteht. Der Grund für solchen Code besteht wahrscheinlich in diversen Performancemythen.
-
Nexus schrieb:
Scorcher24 schrieb:
Vielleicht in dem Fall nicht so schlimm, ich mags trotzdem nicht. Nutze include-guards.
Wenn man nicht alle Compiler unterstützen will, kann man das ruhig machen, auch wenn du es nicht magst. Man muss sich nämlich keine Makros ausdenken und gegebenenfalls ändern, hat weniger zu schreiben und der Präprozessorvorgang läuft möglicherweise schneller ab. Auch wenn das keine enormen Vorteile sind.
Wenn man beide Vorteile will, dann macht man eben beides. Wenn der Compiler das pragma nicht unterstützt (ursprünglich war es afaik nur VS-spezifisch), dann wird es einfach ignoriert und die include guards greifen.
Makros denke ich mir nie selber aus. Die werden von einem kleinen Addin, dass ich für VS gemacht habe automatisch generiert (wie auch das ganze Standard Zeugs, wie include guards und passende .cpp), wenn ich eine Datei (.h) anlege.
-
drakon schrieb:
Wenn man beide Vorteile will, dann macht man eben beides.
Das hingegen vereint wirklich nur Nachteile, es sei denn, man ist auf die Präprozessorgeschwindigkeit angewiesen. Ansonsten gibt es mehr zu schreiben, mit Dateinamen konsistent zu halten, und auf anderen Compilern hat man lästige Warnungen (es sei denn, man führt noch weitere
#ifdefs ein, was aber definitiv hässlich wird).
-
Also Headerguards selbst zu schreiben ist unsinnig. Die kann man sich schön generieren lassen und dann mit einem Zeitstempel drin und man hat nie Probleme mit Konsistenz (wer zwingt denn einen den mit dem Dateinamen zu identifizieren? Projektname und Zeitstempel sollten ausreichend sein). Und dass es Warnungen gibt wüsste ich jetzt nicht und wenn schon kann man, wenn die einen stören ja bestimmt irgendwo ausschalten. Und selbst wenn nicht habe ich lieber ein paar Warnungen, als etwas, dass nicht kompiliert.
Ob ich jetzt mit oder ohne Headguards/pragma die Dateien erzeuge spielt für mich keine Rolle, aber funktionieren tut es dann überall und dort, wo es geht auch noch ein wenig schneller.
Aber ich weiss auch nicht, warum wir hier über solchen Nonsens diskutieren müssen.
-
drakon schrieb:
Also Headerguards selbst zu schreiben ist unsinnig.
Wäre dies so, würden das nicht etliche C++-Bibliotheken tun.
drakon schrieb:
Aber ich weiss auch nicht, warum wir hier über solchen Nonsens diskutieren müssen.
Ich hab Scorcher24 lediglich darauf hingewiesen, dass
#pragma oncemanchmal gerechtfertigt sei. Es hat dich niemand gezwungen, darauf zu antworten.
-
Nexus schrieb:
drakon schrieb:
Also Headerguards selbst zu schreiben ist unsinnig.
Wäre dies so, würden das nicht etliche C++-Bibliotheken tun.
Woher weisst du wie die ihre Headerguards erstellen?
Nexus schrieb:
drakon schrieb:
Aber ich weiss auch nicht, warum wir hier über solchen Nonsens diskutieren müssen.
Ich hab Scorcher24 lediglich darauf hingewiesen, dass
#pragma oncemanchmal gerechtfertigt sei. Es hat dich niemand gezwungen, darauf zu antworten.Ich habe ergänzt, dass man beides machen kann und du hast gesagt, dass es nur Nachteile hat und dann lediglich Tipparbeit und Warnungen genannt und dass das keine wirklichen Punkte sind habe ich ja bereits gesagt.
Ob die Vorteile(kompiliert überall und dort wo es geht auch noch schneller) die Nachteile(ev. (abschaltbare) Warnungen) überwiegen muss jeder selbst entscheiden. Die einzelnen Versionen haben jeweils Nachteile, welche die vereinte Variante nicht hat (kompiliert nicht überall, resp. langsamer).
-
drakon schrieb:
Woher weisst du wie die ihre Headerguards erstellen?
Sie enthalten zumindest keine Timestamps und sind semantisch nach den Inhalten der Datei benannt. Ob gar kein Tool verwendet wird, oder ein Snippet, zu dem man nur noch den Makro-Namen eingibt o.Ä., kann ich nicht sagen.
drakon schrieb:
Ich habe ergänzt, dass man beides machen kann und du hast gesagt, dass es nur Nachteile hat
...sofern man nicht auf den Geschwindigkeitsgewinn durch
#pragma onceangewiesen ist.drakon schrieb:
und dann lediglich Tipparbeit und Warnungen genannt und dass das keine wirklichen Punkte sind habe ich ja bereits gesagt.
Ja, die Unwichtigkeit habe sogar ich schon mit "Auch wenn das keine enormen Vorteile sind" im ersten Post angedeutet.

Aber stimmt schon, gross zu diskutieren lohnt sich nicht. Zumal wir das wahrscheinlich recht ähnlich sehen, aber wohl ein wenig aneinander vorbeigeredet haben...
-
Danke, das war der Grund! Da war nur noch ein Problem: In der Klasse habe ich inline einen Operator /= definiert, jetzt habe ich den Operator nur in der Klasse icMatrix deklariert und ihn in icMatrix.cpp definiert, sprich:
icMatrix& operator/= (const icMatrix& a);und
icMatrix::operator/= (const icMatrix& a) { return *this *= icMatrixInvert(a); }Beim erstellen kommen (zum Glück) nur noch 3 Fehler und eine Warnung:
1>------ Erstellen gestartet: Projekt: IonCore, Konfiguration: Debug Win32 ------ 1>Kompilieren... 1>icMatrix.cpp 1>d:\spieleprogrammierung\ioncore\src\icmatrix.cpp(23) : error C4430: Fehlender Typspezifizierer - int wird angenommen. Hinweis: "default-int" wird von C++ nicht unterstützt. 1>d:\spieleprogrammierung\ioncore\src\icmatrix.cpp(23) : error C2556: 'int icMatrix::operator /=(const icMatrix &)': Überladene Funktion unterscheidet sich nur hinsichtlich des Rückgabetyps von 'icMatrix &icMatrix::operator /=(const icMatrix &)' 1> d:\spieleprogrammierung\ioncore\include\icmatrix.h(140): Siehe Deklaration von 'icMatrix::operator /=' 1>d:\spieleprogrammierung\ioncore\src\icmatrix.cpp(23) : error C2040: 'icMatrix::operator /=': 'int (const icMatrix &)' unterscheidet sich von 'icMatrix &(const icMatrix &)' in Bezug auf die Anzahl vorgenommener Dereferenzierungen 1>d:\spieleprogrammierung\ioncore\src\icmatrix.cpp(175) : warning C4244: 'Argument': Konvertierung von 'double' in 'float', möglicher Datenverlust 1>Das Buildprotokoll wurde unter "file://d:\Spieleprogrammierung\IonCore\Debug\BuildLog.htm" gespeichert. 1>IonCore - 3 Fehler, 1 Warnung(en) ========== Erstellen: 0 erfolgreich, Fehler bei 1, 0 aktuell, 0 übersprungen ==========Alle Fehler verweisen direkt auf die Definition des Operators /= und das Warning auf
const float s = (float) (1.0 / tanf(FOV * 0.5));in der Funktion
icMatrixProjection. Vielleicht könnt ihr mich ein bisschen über diese Fehler aufklären, den ersten habe ich nämlich ungewöhnlich oft und ich weiß nicht, was das Problem ist. Zwar habe ich mich darüber informiert, aber ich sehe den Fehler nicht.
-
Ok, ich habe jetzt noch einiges selber gelöst. Ich darf ja nicht einfach
icMatrix::operator/= (const icMatrix& a) { return *this *= icMatrixInvert(a); }schreiben, sondern muss flogendes schreiben:
icMatrix& icMatrix::operator/= (const icMatrix& a) { return *this *= icMatrixInvert(a); }Kein Wunder, warum die Fehler kamen. Nun bleibt nur noch die Warnung, ist diese brechtigt? Oder wie soll ich mit ihr umgehen? Ignorieren?
-
Irgendwer schrieb:
Nun bleibt nur noch die Warnung, ist diese brechtigt? Oder wie soll ich mit ihr umgehen? Ignorieren?
Warnungen sind immer berechtigt. Float hat eine geringere Genauigkeit als double. Warum auch immer du float benutzt, der Compiler merkt, dass du an einer Stelle einen double stillschweigend in einen float konvertierst und warnt dich vor eben dem Genauigkeitsverlust.
Mal abgesehn von der Tatsache, dass es wirklich keinen Sinn macht, mit deinen Kenntnissen schon sowas komplexes wie eine Spiele-Engine anzufangen (da kommt nur Murks raus, da du offensichtlich die nötige Erfahrung nicht besitzt), schau dir mal im Magazin den Artikel zur Operatorüberladung an. Nachdem du den Ratschlag, keine unintuitiven Operatoren anzubieten, beherzigt und die Häfte deiner Operatoren wieder rausgenommen hast, bleibt immernoch einiges zu tun.