Symbole externe non résolu sur les membres de classe statiques

129

En termes très simples:

J'ai une classe qui se compose principalement de membres publics statiques, donc je peux regrouper des fonctions similaires qui doivent encore être appelées à partir d'autres classes / fonctions.

Quoi qu'il en soit, j'ai défini deux variables char statiques non signées dans ma portée publique de classe, lorsque j'essaye de modifier ces valeurs dans le même constructeur de classe, j'obtiens une erreur "symbole externe non résolu" lors de la compilation.

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

    ...

    test();
};

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

Je suis nouveau en C ++ alors allez-y doucement avec moi. Pourquoi je ne peux pas faire ça?

AustinWBryan
la source

Réponses:

145

Vous avez oublié d'ajouter les définitions correspondant à vos déclarations de X et Y

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

quelque part. Vous souhaiterez peut-être également initialiser un membre statique

unsigned char test::X = 4;

et encore une fois, vous faites cela dans la définition (généralement dans un fichier CXX) pas dans la déclaration (qui est souvent dans un fichier .H)

Colin Jensen
la source
4
Si vous écrivez une bibliothèque d'en-tête uniquement, vous pouvez utiliser cette technique pour éviter le fichier cpp: stackoverflow.com/questions/11709859/…
Shital Shah
62

Les déclarations de membres de données statiques dans la déclaration de classe n'en sont pas une définition. Pour les définir, vous devez le faire dans le.CPP fichier pour éviter les symboles dupliqués.

Les seules données que vous pouvez déclarer et définir sont des constantes statiques intégrales. (Les valeurs de enumspeuvent également être utilisées comme valeurs constantes)

Vous voudrez peut-être réécrire votre code comme suit:

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

test::test() {
}

Si vous souhaitez avoir la possibilité de modifier vos variables statiques (en d'autres termes lorsqu'il n'est pas approprié de les déclarer comme const), vous pouvez séparer votre code entre .Het .CPPde la manière suivante:

.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
la source
pourquoi ici en .CPP, c'est "unsigned char test :: X = 1;" au lieu de "test :: X = 1;"? variable statique X déjà définie, pourquoi encore besoin de "caractères non signés"? @sergtk
Penny
@Penny Parce que "test :: X = 1;" est interprétée comme une affectation, alors que nous essayons de faire une définition.
Anonyme:
4

Puisqu'il s'agit du premier thread SO qui m'a semblé apparaître lors de la recherche de "externes non résolus avec des membres const statiques" en général, je vais laisser un autre indice pour résoudre un problème avec des externes non résolus ici:

Pour moi, la chose que j'ai oubliée était de marquer ma définition de classe __declspec(dllexport), et lorsqu'il est appelé depuis une autre classe (en dehors des limites de la DLL de cette classe), j'ai bien sûr obtenu l'erreur externe my non résolue.
Néanmoins, il est facile d'oublier lorsque vous changez une classe d'assistance interne en une classe accessible depuis ailleurs, donc si vous travaillez dans un projet lié dynamiquement, vous pouvez aussi bien vérifier cela.

Johann Studanski
la source
2

dans mon cas, j'ai déclaré une variable statique dans le fichier .h, comme

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

et dans myClass.cpp, j'ai essayé d'utiliser ce m_nMyVar. Il a eu une erreur LINK comme:

erreur LNK2001: symbole externe non résolu "public: classe statique ... Le fichier cpp lié à l'erreur de lien ressemble à:

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

J'ajoute donc le code ci-dessous en haut de myClass.cpp

//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
}

puis LNK2001 est parti.

Penny
la source
0

Dans mon cas, j'utilisais une mauvaise liaison.
Il a été géré en c ++ (cli) mais avec exportation native. J'ai ajouté à l'éditeur de liens -> entrée -> ressource de lien d'assemblage la dll de la bibliothèque à partir de laquelle la fonction est exportée. Mais la liaison native C ++ nécessite un fichier .lib pour "voir" correctement les implémentations dans cpp, donc pour moi aidé à ajouter le fichier .lib à l'éditeur de liens -> entrée -> dépendances supplémentaires.
[Généralement, le code géré n'utilise pas l'exportation et l'importation de DLL, il utilise des références, mais c'était une situation unique.]

whats_wrong_here
la source