klasse mit globaler externer konstanter Variable, die mit interner Verknüpfung definiert ist
-
26-12-2019 - |
Frage
Ich habe diese Situation:
// Test.h
extern const int param;
class Test
{
private:
int i;
public:
int foo();
};
und
// Test.cpp
#include "Test.h"
int Test::foo() { return param*10; }
und
// core.h
#include "Test.h"
const int param = 1; // should have internal linkage later in core.cpp
int do_stuff ();
und
// core.cpp
#include "core.h"
int do_stuff () { Test obj; return obj.foo(); }
int main() { return do_stuff(); }
Es liegt jedoch kein Linkerfehler vor.Wie sieht der Linker zum Testen aus.cpp der const int param
welches ist durch Kern.h im Kern definiert.cpp mit interner Verknüpfung (Standard für konstante Definitionen)?
Wenn ich Kern umschreibe.h wie folgt (zwei Zeilen ändern):
// core.h
const int param = 1;
#include "Test.h"
int do_stuff ();
es kommt ein Linkerfehler wegen Fehlens param
.Und dann, wenn ich es so ändere:
// core.h
extern const int param = 1;
#include "Test.h"
int do_stuff ();
alles funktioniert wieder.
Ich dachte, dass es in der ursprünglichen Situation vielleicht ein automatisches Inlining des Klassentests im Kern gibt.cpp, also dieser Test.cpp ist nicht vorhanden und der gesamte Code befindet sich im Kern.cpp, damit alles funktioniert.Aber warum sollte es dann darauf ankommen, die beiden Linien im Kern zu ändern.h?
Lösung
Ihre Annahme über die interne Verknüpfung für konstante Definitionen ist nicht immer wahr.Siehe den Abschnitt Standard 3.5 Program linkage
, p.3 (Ich zitiere N3690):
Ein Name mit Namespace-Bereich (3.3.6) hat eine interne Verknüpfung, wenn es der Name von ist
eine Variable, Funktion oder Funktionsvorlage, die explizit als statisch deklariert ist;oder,
eine nichtflüchtige Variable, die explizit als const oder constexpr deklariert ist und weder explizit als extern noch als zuvor als externe Verknüpfung deklariert;oder
ein Datenmitglied einer anonymen Gewerkschaft.
Also für den ersten Fall param
hat externe Verknüpfung und alles ist in Ordnung.
Für den zweiten Fall gibt es eine intern verknüpfte param
im Kern.cpp, aber es gibt eine andere deklarierte-nur param
externe Verknüpfung, aber keine Definition.
Im dritten Fall gibt es einen param
wieder.