Ungelöstes externes Symbol für statische Klassenmitglieder

129

Ganz einfach gesagt:

Ich habe eine Klasse, die hauptsächlich aus statischen öffentlichen Mitgliedern besteht, sodass ich ähnliche Funktionen zusammenfassen kann, die noch von anderen Klassen / Funktionen aufgerufen werden müssen.

Wie auch immer, ich habe zwei statische vorzeichenlose Zeichenvariablen in meinem öffentlichen Klassenbereich definiert. Wenn ich versuche, diese Werte im Konstruktor derselben Klasse zu ändern, wird beim Kompilieren der Fehler "ungelöstes externes Symbol" angezeigt.

class test 
{
public:
    static unsigned char X;
    static unsigned char Y;

    ...

    test();
};

test::test() 
{
    X = 1;
    Y = 2;
}

Ich bin neu in C ++, also schont mich. Warum kann ich das nicht tun?

AustinWBryan
quelle

Antworten:

145

Sie haben vergessen, die Definitionen hinzuzufügen, die Ihren Deklarationen von X und Y entsprechen

unsigned char test::X;
unsigned char test::Y;

irgendwo. Möglicherweise möchten Sie auch ein statisches Element initialisieren

unsigned char test::X = 4;

und wieder tun Sie dies in der Definition (normalerweise in einer CXX-Datei), nicht in der Deklaration (die häufig in einer .H-Datei enthalten ist).

Colin Jensen
quelle
4
Wenn Sie nur eine Header-Bibliothek schreiben, können Sie diese Technik verwenden, um eine CPP- Datei zu vermeiden: stackoverflow.com/questions/11709859/…
Shital Shah
62

Statische Datenelementdeklarationen in der Klassendeklaration sind keine Definition von ihnen. Um sie zu definieren, sollten Sie dies in der tun.CPP Datei , um doppelte Symbole zu vermeiden.

Die einzigen Daten, die Sie deklarieren und definieren können, sind integrale statische Konstanten. (Werte von enumskönnen auch als konstante Werte verwendet werden)

Möglicherweise möchten Sie Ihren Code wie folgt umschreiben:

class test {
public:
  const static unsigned char X = 1;
  const static unsigned char Y = 2;
  ...
  test();
};

test::test() {
}

Wenn Sie die Möglichkeit haben möchten, Ihre statischen Variablen zu ändern (dh wenn es unangemessen ist, sie als const zu deklarieren), können Sie Ihren Code zwischen .Hund .CPPauf folgende Weise trennen :

.H:

class test {
public:

  static unsigned char X;
  static unsigned char Y;

  ...

  test();
};

.CPP:

unsigned char test::X = 1;
unsigned char test::Y = 2;

test::test()
{
  // constructor is empty.
  // We don't initialize static data member here, 
  // because static data initialization will happen on every constructor call.
}
sergtk
quelle
warum hier in .CPP "unsigned char test :: X = 1;" anstelle von "test :: X = 1;"? statische Variable X bereits definiert, warum noch "vorzeichenloses Zeichen" benötigen? @sergtk
Penny
@ Penny Weil "test :: X = 1;" wird als Aufgabe interpretiert, während wir versuchen, eine Definition zu erstellen.
Anonymous1847
4

Da dies der erste SO-Thread ist, der mir bei der Suche nach "ungelösten externen Elementen mit statischen const-Elementen" im Allgemeinen aufgefallen ist, werde ich hier einen weiteren Hinweis hinterlassen, um ein Problem mit nicht aufgelösten externen Elementen zu lösen:

Für mich war das, was ich vergessen habe, meine Klassendefinition zu markieren __declspec(dllexport), und als ich von einer anderen Klasse (außerhalb der DLL-Grenzen dieser Klasse) aufgerufen wurde, bekam ich natürlich meinen ungelösten externen Fehler.
Es ist jedoch leicht zu vergessen, wenn Sie eine interne Hilfsklasse in eine Klasse ändern, auf die von einer anderen Seite aus zugegriffen werden kann. Wenn Sie also in einem dynamisch verknüpften Projekt arbeiten, können Sie dies auch überprüfen.

Johann Studanski
quelle
2

In meinem Fall habe ich eine statische Variable in der .h-Datei deklariert, wie z

//myClass.h
class myClass
{
static int m_nMyVar;
static void myFunc();
}

und in myClass.cpp habe ich versucht, dieses m_nMyVar zu verwenden. Es wurde ein LINK-Fehler wie folgt angezeigt:

Fehler LNK2001: ungelöstes externes Symbol "public: static class ... Die mit dem Linkfehler verbundene cpp-Datei sieht folgendermaßen aus:

//myClass.cpp
void myClass::myFunc()
{
myClass::m_nMyVar = 123; //I tried to use this m_nMyVar here and got link error
}

Also füge ich den folgenden Code oben in myClass.cpp hinzu

//myClass.cpp
int myClass::m_nMyVar; //it seems redefine m_nMyVar, but it works well
void myClass::myFunc()
{
myClass::m_nMyVar = 123; //I tried to use this m_nMyVar here and got link error
}

dann ist LNK2001 weg.

Penny
quelle
0

In meinem Fall habe ich eine falsche Verknüpfung verwendet.
Es wurde c ++ (cli) verwaltet, aber mit nativem Export. Ich habe der DLL der Bibliothek, aus der die Funktion exportiert wird, zu Linker -> Eingabe -> Assembly-Link-Ressource hinzugefügt. Für die native C ++ - Verknüpfung ist es jedoch erforderlich, dass die .lib-Datei die Implementierungen in cpp korrekt "sieht". Daher hat es mir geholfen, die .lib-Datei dem Linker hinzuzufügen -> Eingabe -> zusätzliche Abhängigkeiten.
[Normalerweise verwendet verwalteter Code keinen DLL-Export und -Import, sondern Verweise, aber das war eine einzigartige Situation.]

whats_wrong_here
quelle