Angenommen, ich habe die Dateien a.cpp, b.cpp und die Datei c.h. Beide cpp-Dateien enthalten die c.h-Datei. Die Header-Datei enthält eine Reihe von const int-Definitionen, und wenn ich sie kompiliere, erhalte ich keine Fehler und dennoch kann ich diese const-Zahlen verwenden, als ob sie globale Variablen wären. Die Frage ist also, warum erhalte ich keine Kompilierungsfehler, wenn ich mehrere const-Definitionen habe und diese const ints eine globale Reichtweite haben?
Antworten
Zu viele Anzeigen?Dies liegt daran, dass eine const
-Deklaration im Namespace-Bereich eine interne Verknüpfung impliziert. Ein Objekt mit interner Verknüpfung ist nur innerhalb der Übersetzungseinheit verfügbar, in der es definiert ist. Also ist das eine const
-Objekt, das Sie in c.h
haben, tatsächlich zwei verschiedene Objekte, eines intern in a.cpp
und eines intern in b.cpp
.
Mit anderen Worten,
const int x = ...;
ist äquivalent zu
static const int x = ...;
während
int x;
ähnlich ist wie
extern int x;
weil nicht-const
-Deklarationen im Namespace-Bereich eine externe Verknüpfung implizieren. (In diesem letzten Fall sind sie tatsächlich nicht äquivalent. extern
, ebenso wie die explizite Spezifikation der externen Verknüpfung, erzeugt eine Deklaration und keine Definition eines Objekts.)
Beachten Sie, dass dies spezifisch für C++ ist. In C ändert const
nicht die implizierte Verknüpfung. Der Grund hierfür ist, dass das C++-Komitee wollte, dass Sie schreiben können
const int x = 5;
in einem Header. In C würde dieser Header, der aus mehreren Dateien eingebunden ist, Linkerfehler verursachen, da Sie dasselbe Objekt mehrmals definieren würden.
Aus dem aktuellen C++-Standard...
7.1.1 Spezifizierer für Speicherklasse
7) Ein in einem Namensraumumfang deklarierter Name ohne Speicherklasse-Spezifizierer hat eine externe Verknüpfung, es sei denn, er hat aufgrund einer früheren Deklaration eine interne Verknüpfung und sofern er nicht als const deklariert ist. Als const deklarierte Objekte ohne explizite Deklaration als extern haben eine interne Verknüpfung.
3.5 Programm und Verknüpfung
2) Wenn ein Name intern verknüpft ist, kann auf die von ihm bezeichnete Entität durch Namen aus anderen Bereichen der gleichen Übersetzungseinheit verwiesen werden.
Der Präprozessor führt dazu, dass in Headern definierte Dinge in der aktuellen Übersetzungseinheit eingeschlossen werden.
Echter Grund: weil #define
böse ist und sterben muss.
Einige Verwendungen von #define können durch Inline-Funktionen ersetzt werden. Einige - durch const
-Variablendeklarationen. Da #define tendenziell in Header-Dateien vorhanden ist, funktioniert es besser, diese durch const
s am Ort zu ersetzen. Daher die Regel "Konstanten sind standardmäßig statisch".