Ich würde gerne Hilfe bei der Diagnose der Quelle eines doppelten Symbolfehlers erhalten, den ich erhalte, wenn ich versuche, mit g ++ 4.2.1 zu kompilieren.
Der spezifische Fehler ist
%Vor% Der Fehler tritt nur auf, wenn ich diese Deklaration in eine Datei namens Parameters.h
:
Ich habe alle meine Dateien durchsucht, und dies ist der einzige Ort, an dem SOCIODEM_FILENAMES
deklariert ist. Wenn ich die Deklaration auskommentiere, verschwindet der Fehler "Duplikatsymbol".
Ich bin mit Linkerfehlern nicht vertraut (wenn das das ist) und wäre Ihnen bei der Fehlerbehebung behilflich. Alle meine Header-Dateien haben #ifndef...#define...#endif
wrappers. Mein Kompilierbefehl ist
Vielen Dank im Voraus.
Lösungszusammenfassung
Ich habe jetzt in Parameters.h:
%Vor% Alle anderen Definitionen und Deklarationen in Parameter.h sind unverändert. Andrey und andere Kommentatoren fassen einen alternativen Ansatz zusammen, der extern
verwendet, was für meine Zwecke übertrieben ist.
Aus irgendeinem Grund hat sich bisher keine der Antworten darum bemüht, den Unterschied zwischen Ihrem Ganzzahl NUM_SOCIODEM_FILES
-Objekt und dem Array SOCIODEM_FILENAMES
-Objekt zu erklären. Letzteres löst den Linker-Fehler aus den bereits erläuterten Gründen aus: weil Sie Ihre Header-Datei in mehrere Implementierungsdateien einbinden. Die erste Verbindung würde jedoch ohne Probleme hergestellt (da es tatsächlich keine Probleme mit NUM_SOCIODEM_FILES
declaration gibt). Warum?
Der Grund dafür ist, dass Ihr Objekt NUM_SOCIODEM_FILES
zu const
deklariert ist. In C ++ haben const-Objekte standardmäßig interne Verknüpfungen , was bedeutet, dass sie keine Verbindungsprobleme verursachen, selbst wenn sie in mehreren Implementierungsdateien definiert sind. Mit anderen Worten, in C ++ entspricht Ihr NUM_SOCIODEM_FILES
weshalb es zu keinerlei Verbindungsproblemen kommt.
Gleichzeitig wird Ihre SOCIODEM_FILENAMES
nicht als Konstante deklariert, weshalb sie standardmäßig externe Verknüpfung erhält und schließlich zu Linker-Fehlern führt. Aber wenn Sie SOCIODEM_FILENAMES
auch als const
deklarieren, wird das Problem verschwinden.
Beachten Sie, wo die zusätzliche const
in der Deklaration platziert wird. Wenn Sie einfach das zusätzliche const
hinzufügen und alles andere unverändert belassen (dh die Definition beibehalten, wenn SOCIODEM_FILENAMES
in der Header-Datei enthalten ist), wird der Linker den Fehler nicht melden, selbst wenn Sie Ihre Header-Datei in mehrere Übersetzungseinheiten einfügen / p>
Dies ist jedoch kein empfohlener Ansatz, da Sie auf diese Weise Ihre SOCIODEM_FILENAMES
interne Verknüpfung angeben und eine eigenständige Kopie von SOCIODEM_FILENAMES
array in jeder Übersetzungseinheit erhalten - etwas, das gut funktioniert, aber immer noch sehr wenig Sinn. Für Ihr Array ist es normalerweise besser, den in anderen Antworten empfohlenen extern
-Ansatz zu verwenden.
Beachten Sie jedoch, dass Sie dies normalerweise nicht für NUM_SOCIODEM_FILES
declaration tun sollten !!! Es ist in Ordnung, wie es ist, in der Header-Datei definiert. Sofern Sie nicht versuchen, etwas Ungewöhnliches zu tun, sollten skalare Konstanten normalerweise mit Initialisierer in den Header-Dateien definiert werden - so können sie als Kompilierzeitkonstanten in allen Übersetzungseinheiten angesehen werden, was sehr wertvoll ist Ding zu haben. Also, hüte dich vor dem seltsamen Ratschlag in einigen anderen Antworten, die Definition von NUM_SOCIODEM_FILES
in .cpp
file ebenfalls zu verschieben - das macht eigentlich keinen Sinn und ist total falsch, etwas zu tun.
Am wahrscheinlichsten ist, dass Sie diese Datei in mehreren Quelldateien enthalten. Das Problem ist, dass jede Aufnahme zu einer separaten Definition für eine Variable namens #include
führt. Einschließlich Wachen helfen nicht dabei. Wächter einschließen verhindern mehrere Deklarationen innerhalb einer einzigen Kompilierungseinheit; Sie verhindern nicht mehrere Definitionen über mehrere Übersetzungseinheiten hinweg.
Sie müssen diese Variablen im Header als SOCIODEM_FILENAMES
deklarieren und sie dann in genau einer Quelldatei definieren. z.B.
und dann:
%Vor% Sie können damit nicht fertig werden, dies für extern
zu tun, weil es eine konstante Ganzzahl ist, und der Compiler kann sie daher nur als Kompilierzeitkonstante behandeln, und sie wird niemals im kompilierten Code auftauchen. Das int
kann jedoch nicht auf diese Weise behandelt werden und muss genau eine Definition haben (in C ++ als "eine Definitionsregel" bekannt).
Der Header-Guard ( #ifndef..#endif
wrapper) verhindert nur, dass Sie denselben Header mehrmals in einer einzigen Quelldatei einfügen. Sie können immer noch mehrere Quelldateien mit diesem Header haben, und jeder einzelne deklariert dieses Symbol separat. Da sie alle den gleichen Namen haben, führt das Verknüpfen dieser Quellen zu einer Kollision des Symbolnamens. Wahrscheinlich möchten Sie das Symbol in einer Quelldatei anstelle einer Headerdatei deklarieren
Das Problem besteht darin, dass Sie eine Definition in eine Header-Datei einfügen. Wenn Sie diese Datei in mehr als eine Kompilierungseinheit (.cpp-Datei) einschließen, werden Sie in der Tat mehrere Definitionen erstellen und bei der Link-Zeit erhalten Sie diesen Fehler.
Sie müssen beide Definitionen in eine CPP-Datei einfügen und nur eine Deklaration in die Header-Datei einfügen:
%Vor% Wie andere vorgeschlagen haben, besteht eine Möglichkeit darin, NUM_SOCIODEM_FILES
und SOCIODEM_FILENAMES
als extern
zu deklarieren und sie einmal in einer externen Datei zu definieren. Die andere Möglichkeit besteht darin, sie als static
zu deklarieren - dies führt dazu, dass sie in jeder Objektdatei, die den Header enthält, dupliziert werden, aber keinen Fehler erzeugen, da die Definition für diese Objektdatei privat ist. Welche Option Sie wählen, hängt ganz von Ihren eigenen Vorlieben ab.