Statische Klassenelemente
-
Hey ihr,
Habe eben ein Beispiel im Netz zu statischen Klassenelementen gefunden und mal nen ganz leichtes Beispiel programmiert:
#include <iostream> using namespace std; class X { private: static int x; public: static void setx(int z) { x = z; } static int getx(void) { return x; } }; int X::x; int main(void) { X y; X::setx(4); cout << X::getx() << endl; system("Pause"); }Diese Version funktioniert.
Sie funktioniert aber nur, wenn ich vor der Main-Funktion X::x deklariere.
Woran liegt das, da X ja auch schon innerhalb der Main-Funktion deklariert wird.
Verschiebe ich "int X::x" in die Mainfunktion meckert ja auch der Compiler.
Warum dieses Doppelte Vorkommen?cya
David
-
Zu jeder Variable benötigst du eine Definition (die dem Compiler/Linker sagt, wo der Speicherplatz für diese Variable liegt) - auch für Klassenmember. "normale" Member werden automatisch mit den Objekten definiert, die du anlegst, aber statische Member liegen irgendwo außerhalb - und darum brauchst du auf globaler Ebene diese Definition "int X::x;" (üblicherweise kommt die nicht in die main.cpp, sondern in die X.cpp).
-
Ist die "X.cpp" einfach die Cpp-Datei, welche alle statischen Definitionen enthält?
Kann ich auch .cpp's in mein Projekt einbinden? Nicht nur H's?
-
777 schrieb:
Ist die "X.cpp" einfach die Cpp-Datei, welche alle statischen Definitionen enthält?
Grob gesagt ja - hauptsächlich enthält sie die Methodendefinitionen der Klasse X, die zu umfangreich für inline sind. (und eben auch statische Member der Klasse

Kann ich auch .cpp's in mein Projekt einbinden? Nicht nur H's?
Ja, kannst du - aber besser nicht per #include. Du kannst dem Compiler mehrere CPP-Dateien mitgeben, die er nacheinander alle übersetzt und gemeinsam an den Linker übergibt (IDEs wie MSVC jagen alle CPP's im Projekt durch den Compiler, bei Commandozeilen-Compilern oder Makefiles mußt du alle hintereinander angeben (z.B. "gcc main.cpp x.cpp -o programm")
-
Aber an der Stelle wundert mich dann, warum es überhaupt die Endung "h" und "cpp" gibt.
Ich dachte, dass die "h"- Datei am besten immer Klassen oder Funktionen enthalten soll, welche sich nur kompilieren lassen, wenn diese Datei in eine "cpp"-Datei eingebunden wird, welche eine Main-Funktion enthält?
Kennt jemand eine Seite, wo über die verschiedenen Endungen und ihre Bedeutung/Inhalt aufgeklärt wird?
-
".H" ist ein "Header" - der enthält normalerweise nur Deklarationen der Klassen und Funktionen.
".CPP" ist ein Quellfile - das enthält die dazugehörigen Definitionen.Und normalerweise hat du für deine Klasse(n) einen Header und eine Quelldatei - sowie eine weitere Quelldatei mit der main()-Funktion, die diese Klasse verwendet.
-
Thx!!!
Warum ist dann #include bei Cpp-Dateien schlimm?
Ich mein es funktioniert doch, oder?
Wie kann ich das bei Dev-C++ auch anders machen? :xmas1:
-
Es ist zumindest ungewohnt. Und IDEs compilieren normalerweise JEDE .cpp Datei im aktuellen Projekt extra, wenn sie ein Programm erstellen - da wird sich dann der Linker beschweren, wenn die selbe Definition an verschiedenen Stellen auftaucht.
PS: Und wenn du beginnst, größere Projekte zu entwickeln, wirst du schnell den Vorteil erkennen, daß die .cpp's jede für sich übersetzt werden können.
-
CStoll schrieb:
Es ist zumindest ungewohnt. Und IDEs compilieren normalerweise JEDE .cpp Datei im aktuellen Projekt extra, wenn sie ein Programm erstellen - da wird sich dann der Linker beschweren, wenn die selbe Definition an verschiedenen Stellen auftaucht.
PS: Und wenn du beginnst, größere Projekte zu entwickeln, wirst du schnell den Vorteil erkennen, daß die .cpp's jede für sich übersetzt werden können.
außer bei Templates, da nervt das bisweilen, deswegen sind die meisten auch headeronly, außer man legt sich auf bestimmte Datentypen der Templates fest, was man eigentlich auch recht nett nutzen kann
-
777 schrieb:
Thx!!!
Warum ist dann #include bei Cpp-Dateien schlimm?
Ich mein es funktioniert doch, oder?
Wie kann ich das bei Dev-C++ auch anders machen? :xmas1:kommt drauf an, was drin steht.
ein programm besteht aus verschiedenen übersetzungseinheiten (translation/compilation units), jede davon wird einzeln kompiliert und der linker fügt die durchgekauten ÜEs dann zu einem programm zusammen. idR ist es so, dass deine *cpp dateien je eine übersetzungseinheit repräsentieren. die header, die du inkludierst gehören allerdings zu dieser übersetzungseinheit dazu (denn zum zeitpunkt des kompilierens sind die direktiven "#include" usw. schon vom präprozessor verarbeitet worden - es gibt dann also nur mehr eine gewisse anzahl (nämlich die anzahl der *cpp datein) an übersetzungseinheiten)
da jetzt aber unterschiedliche *.cpp dateien jeweils dieselben header inkludieren können, dürfen in header-dateien auch nur solche sachen drinstehen, bei denen es egal ist, dass sie in mehreren ÜEs vorkommen.
bei der definition einer statischen klassenvariable ist es z.b. nicht egal. diese würde dann in mehreren ÜEs definiert werden und der linker wüsste nicht, welche jetzt die richtige wäre, es gäbe also ein problem beim linken.
ein anderes beispiel (ähnlich) ist die definition von globalen variablen. in header dateien darfst du diese nur *deklarieren*, nicht aber definieren (=speicher für sie bereitstellen), weil dann im endeffekt ja in jeder *.cpp datei, die diesen header inkludiert, eine definition für die globale variable vorhanden wäre. dafür gibt es bei globalen variablen das schlüsselwort "extern".
eine andere lösung ist es, objekte zu definieren, die nur jeweils für eine einzige ÜE gültig sind, dann kann es über das gesamtprogramm gesehen, mehrere davon geben, und jede übersetzungseinheit hat ihre eigene davon.das erreicht(e) man (früher) mit static
//header.h static int x; void foo (); //x.cc #include "header.h" //... void foo () { cout << x; } //main.cc #include "header.h" //... int main () { x++; foo(); //gibt *nicht* 1 aus. }und heutzutage mit unnamed namespaces.