header / cpp
-
ich meine nicht zusätzliche header dateien.
was ich meine ist, wenn ich deklaration und definition trenne, dann müssen die ja irgendwie voneinander wissen und das kann man ja durch includen der cpp am ende der header oder includen der header am anfang der cpp datei machen. natürlich mit entsprechenden #ifndef ... #define ... #endif abfragen, um dopplungen zu vermeiden.
zu den zusätzlichen header dateien, die man evtl. benötigt hat mir mal jemand gesagt, header-dateien gehören in header-dateien, also das man benötigte header in die header-datei includet.
-
FreakyBKA schrieb:
und das kann man ja durch includen der cpp am ende der header [...] machen.
Nein. Aber die Variante mit den Headern am Anfang der .cpp-Datei.
Du kannst dir aber vorstellen, dass eingefügte Header (im Normalfall) wie normaler Code behandelt werden. Sie werden an der Stelle in den Quellcode eingefügt, an dem die
#include-Direktive steht.FreakyBKA schrieb:
wenn ich deklaration und definition trenne, dann müssen die ja irgendwie voneinander wissen
Die Deklaration muss zum Zeitpunkt der Definition bekannt sein, und nicht umgekehrt. Mit Headern kannst du die gleiche Abfolge (z.B. Deklaration im Header, Definition in der .cpp-Datei) erzielen.
-
und warum geht die variante mit der cpp am ende der header nicht?
ich hab da nämlich grad das problem, dass wenn ich diese verlinkung entferne ich bei einigen meiner klassen, die Linkerfehlermeldung "unresolved external symbol" bekomme.
-
FreakyBKA schrieb:
und warum geht die variante mit der cpp am ende der header nicht?
ich hab da nämlich grad das problem, dass wenn ich diese verlinkung entferne ich bei einigen meiner klassen, die Linkerfehlermeldung "unresolved external symbol" bekomme.Es geht (zumindest in einem akzeptablen Compiler) nicht, weil die .cpp-Datei kompiliert wird. Wenn dort keine Inkludierung der Header vorkommt, können diese auch nicht verarbeitet werden.
Was dein Problem betrifft: Hast du es versucht, die Header am Anfang der .cpp-Datei einzubinden? Zeig mal ein Stück Code...
-
also meine bisherigen sachen sehen immer so aus:
Header (zB. foo.h)
#ifndef foo_h #define foo_h class foo { foo(); //weitere deklarationen }; #include "foo.cpp" #endifCpp (zB. foo.cpp)
#ifndef foo_cpp #define foo_cpp #include "foo.h" foo::foo() { //... }; //weitere definitionen #endifund das hat bisher auch immer funktioniert, vllt liegt das auch am VS2008EE-Compiler, das der sowas "richtig" interpretiert
-
Nein, den Compiler hab ich auch. Aber foo.cpp wird wegen der
#ifndef-Direktive in der .cpp-Datei gar nicht mehr eingebunden.Aber wieso machst du das so umständlich? Auf folgende Weise ginge es viel einfacher, dann könntest du dir auch die Abfragen wegen doppelter Inkludierung sparen. Ausserdem verwechselst du Deklarationen mit Definitionen.
Header:
class foo { foo(); // Das sind DEKLARATIONEN! };CPP-Datei:
#include "foo.h" foo::foo() // Das sind DEFINITIONEN! { } // KEIN SEMIKOLON!!! int main() { }
-
hab mich bei den definitionen und deklarationen nur verschrieben, habs ja auch gleich korrigert.
warum sind die semikolon denn da falsch? funktioniert doch auch.
naja die #ifndef sachen hab ich ja drin falls ich indirekt zweimal den gleichen header einbinde und der dann nicht rummeckert, das er den schon kennt.
-
FreakyBKA schrieb:
warum sind die semikolon denn da falsch? funktioniert doch auch.
Natürlich funktioniert es, das Semikolon ist jedoch überflüssig. Man nennt ein einziges ; eine Leeranweisung, da es nichts bewirkt. Und in C++ muss am Ende eines Blockes kein Semikolon geschrieben werden (ausser bei Klassen, da diese Datentypen sind).
FreakyBKA schrieb:
naja die #ifndef sachen hab ich ja drin falls ich indirekt zweimal den gleichen header einbinde und der dann nicht rummeckert, das er den schon kennt.
Das ist ja schön und gut, aber deswegen brauchst du trotzdem nicht im Header die CPP-Datei einzubinden.
-
FreakyBKA schrieb:
naja die #ifndef sachen hab ich ja drin falls ich indirekt zweimal den gleichen header einbinde und der dann nicht rummeckert, das er den schon kennt.
Die Includeguards gehören ausschließlich in die Dateien die du inkludierst (Sprich Header). Davon abgesehen ist es üblich Makros (defines) immer groß zu schreiben. Semikolons sind an den von Nexus erwähnten stellen unnötig (und gehören dort auch nicht hin), der Compiler wird dies aber durchgehen lassen.
Also ganz kurz das Beispiel angepasst:
// foo.h
#ifndef FOO_HEADER #define FOO_HEADER class foo { public: foo(); }; #endif// foo.cpp
#include "foo.h" foo::foo() { }// main.cpp
#include "foo.h" int main() { foo f; }cu André
-
dann versteh ich aber nicht woher eine andere datei, in der ich nur die header inkludieren würde, weiß wie die entsprechenden definitionen aussehen. ich mein der sieht doch in seinem code dann nur die deklarationen ohne die definitionen.
also wenn ich mir irgendwo fooA.h und fooA.cpp definiere und nur fooA.cpp die fooA.h includiert. wenn ich jetzt in fooB.h die fooA.h includieren dann kennt die doch die ganzen definitionen aus fooA.cpp nicht, oder bin ich da jetzt auf dem flaschen dampfer? oder wenn ich in der main.cpp einfach nur fooA.h includiere, ist das ja der ähnliche fall.
-
Makro (defines) schreib ich sonst auch immer groß, hab hier jetzt nur der schnelle halber nicht darauf geachtet.
-
FreakyBKA schrieb:
also wenn ich mir irgendwo fooA.h und fooA.cpp definiere und nur fooA.cpp die fooA.h includiert.
Wie oft müssen wir dir noch sagen, dass man keine CPP-Dateien in Header inkludiert?
Es macht bei einer Klasse nichts, wenn die Definition von deren Memberfunktionen nicht bekannt ist, solange du die Funktionen nicht aufrufst.
-
hab ich doch auch gar nicht geschrieben, dass ich .cpp in .h inkludiere sondern umgedreht.
main.cpp
#include "fooA.h" /*deklariert die klasse fooA*/ int main() { fooA A; return 0; }hier versteh ich dann nicht woher die main.cpp weiß wie die fooA-Klasse definiert ist?
-
FreakyBKA schrieb:
main.cpp
#include "fooA.h" /*deklariert die klasse fooA*/ int main() { fooA A; return 0; }hier versteh ich dann nicht woher die main.cpp weiß wie die fooA-Klasse definiert ist?
Ganz einfach: gar nicht!
Der Compiler benötigt nur eine Deklaration. Die ist in der Headerdatei vorhanden. Der Compiler merkt nun, dass die Definition nicht in der gleichen Quelldatei ist und markiert das in der erzeugten Objektdatei entsprechend.
Im zweiten Schritt kommt der Linker (dieser benötigt die Definitionen) und ersetzt diese Markierungen durch Verweise auf den aus einer anderen Quelldatei erstellten Funktionen.
-
*schnipp*
Da hatte es 2 Seiten..

-
Ups sorry, da hab ich nicht genau gelesen

Um mal die beiden vorherigen Beiträge zu ignorieren (:p):
Wie gesagt, so lange du keine der noch nicht definierten Funktionen aufrufst, geht alles ohne Probleme. Wenn du aber einen neuen Standardkonstruktor schreibst, muss dieser definiert sein, damit du eine Instanz der Klasse erstellen kannst.
Beim Aufruf nicht-definierter Funktionen erhältst du diesen Linker-Error: error LNK2001: Nicht aufgelöstes externes Symbol ""public: __thiscall ...
-
Beim Aufruf nicht-definierter Funktionen erhältst du diesen Linker-Error: error LNK2001: Nicht aufgelöstes externes Symbol ""public: __thiscall ...
genau das erhalte ich jetzt, nachdem ich überall die inkludierung der cpp-dateien aus den header-dateien rausgenommen habe

Im zweiten Schritt kommt der Linker (dieser benötigt die Definitionen) und ersetzt diese Markierungen durch Verweise auf den aus einer anderen Quelldatei erstellten Funktionen.
woher nimmt er die verweise? er weiß doch gar nicht wo ich die entsprechende .cpp habe.
-
Doch. Dafür werden ja die anderen Source Dateien mitgelinkt.
-
dh ich muss jede einzelne cpp-Datei, die ich irgendwann mal erstellt habe und verwenden will, mit ins projekt aufnehmen? genau das wollte ich eigentlich vermeiden um das projekt übersichtlich zu halten.
-
FreakyBKA schrieb:
Beim Aufruf nicht-definierter Funktionen erhältst du diesen Linker-Error: error LNK2001: Nicht aufgelöstes externes Symbol ""public: __thiscall ...
genau das erhalte ich jetzt, nachdem ich überall die inkludierung der cpp-dateien aus den header-dateien rausgenommen habe

Zeig doch mal deinen aktuellen Code. Das sollte eigentlich nicht passieren. Du hast ja die benötigten Methoden schon definiert, oder?