Warum sollte ich die statische Variable im Header nicht initialisieren? [Duplikat]

8

Also, sagen wir, ich habe einen Header wie folgt:

%Vor%

Ich habe schon oft gehört, dass ich statische Variablen nicht in einer Kopfzeile, sondern in cpp initialisieren sollte. Aber da es Wachen gibt, sollte es nur eine Kopie von BaseClass :: x geben. Also verstehe ich irgendwie nicht, warum ich

setzen sollte %Vor%

in cpp. Danke.

    
user3496846 04.04.2014, 17:55
quelle

4 Antworten

9

Wenn Sie dies in der Kopfzeile tun, erhalten Sie mehrere Definitionsfehler, sobald Sie sie aus mehr als einer CPP-Datei einfügen. Sie sagen dem Compiler wirklich zwei Dinge, wenn Sie

deklarieren %Vor%

Zuerst definieren Sie das Symbol BaseClass :: x; Zweitens sagen Sie, dass Sie möchten, dass es den Anfangswert von 10 hat. Gemäß der One Definition-Regel kann dies nur geschehen geschehen einmal in Ihrem Programm.

    
Nathan Monteleone 04.04.2014, 17:57
quelle
4

Die Wächter verhindern nicht mehrere Kopien in mehreren Quelldateien. Sie verhindern nur mehrere Kopien in einer Quelldatei.

Sie verstoßen gegen die eine Definitionsregel, wenn Sie mehrere Quelldateien haben, die #include "base_class.h" .

    
David Hammen 04.04.2014 18:00
quelle
4

Vielleicht ist es einfacher zu verstehen, wenn Sie darüber nachdenken, was der Präprozessor tatsächlich macht: Er kopiert den Inhalt aller enthaltenen Header-Dateien in die cpp-Datei und übergibt diese an den Compiler.

Nehmen wir an, Sie haben:

%Vor%

Nachdem der Präprozessor die Includes erweitert hat, enthalten beide Dateien:

%Vor%

Sobald nun beide Objektdateien an den Linker übergeben werden, wird das Symbol% ​​co_de% zweimal angezeigt - was ein Fehler ist.

Um es noch deutlicher zu machen, stell dir vor, du würdest das in eine Header-Datei schreiben:

%Vor%

Und dann fügen Sie es in zwei verschiedene cpp-Dateien ein, die beide in einer ausführbaren Datei verknüpft sein sollten. Es ist eigentlich nicht anders als Ihr Beispiel, wenn man es aus der Sicht des Linkers sieht.

Warum ist das kein Problem mit Klassendeklarationen?

Es gibt einen Unterschied zwischen Deklarationen und Definitionen . Nur letzteres wird Probleme verursachen. Zum Beispiel sind alle folgenden Deklarationen:

  • BaseClass::x
  • extern int a;
  • void foo(int a);

Dies sind Definitionen:

  • class Foo { int bar(); };
  • int a;
  • int b = 10;
  • void foo(int a) { /*..*/ }

Solange es eine (und nur eine) Definition gibt, können Sie so viele Deklarationen haben, wie Sie möchten, und der Linker stellt sicher, dass alle auf dieselbe Funktion oder denselben Speicherort verweisen.

Was ist mit Klassen? Klassen können nur deklariert werden, während ihre Elementfunktionen und statischen Mitglieder definiert werden müssen. Auch hier darf jede Definition nur einmal vorkommen.

Memberfunktionen und statische Member existieren tatsächlich nur einmal im Adressraum eines Programms, während normale Member (Instanzvariablen) für jedes Objekt der Klasse existieren.

Zurück zu Ihrem spezifischen Problem: statische Member sind im Grunde nur globale Variablen, sind aber auf den Klassennamen beschränkt.

Hoffe, das macht die Dinge für dich klar!

    
lethal-guitar 04.04.2014 18:06
quelle
2

Weil, wenn Sie es in der Kopfzeile initialisieren, besteht die Möglichkeit, dass es an mehreren Stellen definiert wäre, wenn Sie die Kopfzeile mehr als einmal einschließen. Das wird zu einem Linker-Fehler

führen     
ununpentium-299 04.04.2014 17:59
quelle

Tags und Links