static const in Headern?
-
Vielen Dank Caipi!
Das hat mein Verständnis der Materie etwas verbessert.
Als ich in den Büchern gelesen habe, dass für statische Variablen nur einmal Speicher reserviert wird, wollte ich die Konstante global und statisch machen, da sie nur einmal im Speicher zu liegen braucht, auch wenn mehrere Einheiten sie verwenden.
Wenn ich Dich recht verstanden habe, dann geht sowas gar nicht!?
Ausser ich deklariere sie in Globals.h und definiere sie in Globals.cpp.
Danach kann ich sie mit Globals::tagEnd doch irgendwie in nem anderen Header verwenden, wenn ich dort Globals.h inkludiere, oder?Ciao
Reth
-
Reth schrieb:
Als ich in den Büchern gelesen habe, dass für statische Variablen nur einmal Speicher reserviert wird, wollte ich die Konstante global und statisch machen, da sie nur einmal im Speicher zu liegen braucht, auch wenn mehrere Einheiten sie verwenden.
Das ist nicht ganz korrekt. Korrekt ist, dass innerhalb einer Übersetzungseinheit nur einmal Speicher für eine als static deklarierte Variable reserviert wird.
Für globale nicht-statische Objekte bzw. Variablen wird innerhalb des gesamten Programms (d.h. innerhalb aller ÜEs) nur einmal Speicher reserviert - nämlich zum Zeitpunkt der _Definition_ der selbigen. (Andernfalls beschwert sich der Linker).
Ein weiterer Unterschied zwischen globalen als static deklarierten Objekten und globalen _nicht_ als static deklarierten Objekten, der mit obigen Gegebenheiten zusammenhängt, ist das Linkage. D.h. ob und wie sie mit anderen Übersetzungseinheiten verbunden werden.
Merke:
1.) Globale als static deklarierte Bezeichner haben internes Linkage, d.h., dass sie außerhalb der ÜE, in der sie definiert wurden, nicht ansprechbar sind.
2.) Globale _nicht_ als static deklarierte Bezeichner haben externes Linkage, d.h., dass sie von jeder ÜE angesprochen werden können.Beispiel zu 1:
(mit den Übersetzungseinheiten (Modulen) foo.cpp, bar.cpp und dem Header header.hpp)// header.hpp static const int static_var; // Definition einer konstanten statischen Variable vom Typ in. // foo.cpp: #include "header.hpp" // inkludiert den Header, der die static_var definiert. // Du kannst in diesem Modul nun static_var benutzen. int main() { ... } // bar.cpp: // In diesem Modul kannst du static_var aus foo.cpp _nicht_ verwenden, da es internes Linkage // besitzt. Falls du hier ebenfalls den Header header.hpp einbindest, enthält // dieses Modul ebenfalls eine statische Variable namens static_var, die nicht // mit dem gleichnamigen Bezeichner aus foo.cpp kollidiert. (Weil internes linkage).Beispiel zu 2: (siehe mein erster Post).
Wenn ich Dich recht verstanden habe, dann geht sowas gar nicht!?
Was geht nicht? Eine static deklarierte Variable in einer ÜE zu benutzen, in der sie nicht definiert wurde? Nein. Das geht nicht. Warum auch? Du kannst die Variable einfach nicht statisch deklarieren und hast externes Linkage.
Ausser ich deklariere sie in Globals.h und definiere sie in Globals.cpp.
Danach kann ich sie mit Globals::tagEnd doch irgendwie in nem anderen Header verwenden, wenn ich dort Globals.h inkludiere, oder?Wieso Globals::tagEnd? Ansonsten ist dein Gedankengang aber korrekt.
Btw: AFAIK gibt es in der C++-FAQ auch einen Thread zu diesem Thema.
Gruß Caipi
-
Also das Ganze funzt nicht so recht, irgendwas mach ich noch falsch!
Habs nun so:
Datei Globals.cc:
#indeluce <Header für struct TagItem> const struct TagItem tagEnd = {TAG_END, 0L};Datei WindowDataC.h:
... private: extern const struct TagItem tagEnd; ...Nun meckert der G++ in dieser Stelle:
storage class specified for field `tagEnd'Was will er mir denn damit sagen?
Im make-File wird Globals.cc vor den Dateien übersetzt, welche WindowDataC.h verwenden!Was mach ich noch falsch?
Ciao
Reth
-
Reth schrieb:
Was mach ich noch falsch?
Falsch ist, dass du versuchst eine globale Variable in den Private-Bereich einer Klasse zu stecken. Das ist imho schon von der Denkweise der verkehrte Ansatz. Einerseits willst du eine konstante, globale Variable haben, willst diese dann aber in deiner Klasse wieder vor dem Zugriff von außen "verstecken", willst diese also in der Klasse wieder lokal machen.
Gruß Caipi
-
Das kann sein. Wie gesagt bin absoluter C++ Newbie und dazu noch sehr sehr Java-lastig!
Da gibts immer nur Klassen!
Wie muss ich denn nun die externe Variable in WindowDataC.h verwenden, damit es funktioniert? Im Public-Teil oder gar außerhalb der Klassendefinition?
Ciao
Reth
-
Globale Variablen gehören immer außerhalb der Klassendefinition. (alles in der Definition ist ein Teil der jeweiligen Klasse)
-
Vielen Dank. Das habe ich gestern noch ausprobiert und es hat gefunzt, habs nur noch nicht gepostet.
Aber um mal zitiert zu Fragen: Nun, warum ist das so? Sprich: Was ist das Konzept dahinter?
Ciao
Reth
-
Wie ich gerade schon gesagt habe - alles, was innerhalb der Klassendefinition steht, ist ein Teil der Klasse und deshalb nur im Zusammenhang dieser Klasse verwendbar. C hat (im Gegensatz zu Java) einen globalen Namensraum, in den alle Klassen-unabhängigen Definitionen gehören.
-
Naja, es müsste so heißen:
// .hh class Foo { private: const TagItem tagEnd; ... } // .cc const Foo::TagItem tagEnd = {TAG_END, 0L};Das 'struct' kannste dir Sparen. Das war nur in C so, nicht aber in C++.
-
Welcher weg ist denn der richtige, oder gehen beide.
Ich hab nun:
Globals.cc const struct TagItem tagEnd = {TAG_END, 0L;}; WindowDataC.h extern struct TagItem tagEnd; class ...Das wird mal compiliert.
Brauch ich struct wirklich nicht mehr, auch wenn TagItem ne Struktur aus nem Header der Betriebssystemfunktionen ist?Ciao
-
In C++ brauchst du das wirklich nicht. Egal wie und wo deine struct declariert ist. Wenn der C++-compiler einen C-header list wird daraus c++ code. Das ist auch der Grund warum du Linker-Fehler bekommst wenn du einen c-header einbindest wo das extern "C" fehlt.
Kurt