152 votes

Symbole externe non résolu sur les membres de la classe statique

C'est très simple :

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

Quoi qu'il en soit, j'ai défini deux variables statiques de type char non signé dans la portée publique de ma classe. Lorsque j'essaie de modifier ces valeurs dans le constructeur de la même classe, j'obtiens une erreur "unresolved external symbol" à la compilation.

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

    ...

    test();
};

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

Je suis nouveau dans le domaine du C++, alors allez-y doucement. Pourquoi est-ce que je ne peux pas faire ça ?

172voto

Colin Jensen Points 1555

Si vous utilisez C++ 17 vous pouvez simplement utiliser le inline (voir https://stackoverflow.com/a/11711082/55721 )


Si vous utilisez des versions plus anciennes de la norme C++, vous devez ajouter les définitions correspondant à vos déclarations de X et Y

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

quelque part. Vous pourriez également initialiser un membre statique

unsigned char test::X = 4;

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

77voto

sergtk Points 3109

Les déclarations de membres de données statiques dans la déclaration de la classe ne constituent pas une définition de ceux-ci. Pour les définir, vous devez le faire dans la section .CPP pour éviter la duplication des symboles.

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

Vous pourriez 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 voulez avoir la possibilité de modifier vos variables statiques (en d'autres termes, lorsqu'il n'est pas approprié de les déclarer comme constantes), vous pouvez séparer votre code entre les éléments suivants .H y .CPP de 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.
}

9voto

Penny Points 183

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

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

et dans myClass.cpp, j'ai essayé d'utiliser ce m_nMyVar. J'ai obtenu une erreur de type LINK :

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

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

J'ai donc ajouté le code suivant 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
}

alors LNK2001 est parti.

6voto

Johann Studanski Points 121

Étant donné que c'est le premier fil de discussion de l'OS qui m'est apparu lors d'une recherche sur les "éléments externes non résolus avec des membres statiques const" en général, je vais laisser ici une autre indication pour résoudre un problème avec les éléments externes non résolus :

Pour moi, ce que j'ai oublié, c'est de marquer la définition de ma classe. __declspec(dllexport) et lorsqu'il est appelé depuis une autre classe (en dehors des limites de la dll de cette classe), j'obtiens bien sûr l'erreur externe non résolue.
Cependant, il est facile d'oublier que l'on remplace une classe d'aide interne par une classe accessible depuis un autre endroit, donc si vous travaillez dans un projet à liaison dynamique, vous pouvez aussi vérifier cela.

5voto

Sanya Tayal Points 31

Lorsque nous déclarons une variable statique dans une classe, elle est partagée par tous les objets de cette classe. Comme les variables statiques ne sont initialisées qu'une seule fois, elles ne sont jamais initialisées par un constructeur. Au lieu de cela, la variable statique doit être initialisée explicitement en dehors de la classe, une seule fois, à l'aide de l'opérateur de résolution de portée (: :).

Dans l'exemple ci-dessous, la variable statique counter est un membre de la classe Demo. Notez comment elle est initialisée explicitement en dehors de la classe avec la valeur initiale = 0.

#include <iostream>
#include <string>
using namespace std;
class Demo{
   int var;
   static int counter;

   public:
   Demo(int var):var(var){
      cout<<"Counter = "<<counter<<endl;
      counter++;
   }
};
int Demo::counter = 0;                 //static variable initialisation
int main()
{
   Demo d(2), d1(10),d3(1);
}

Output:
Count = 0
Count = 1
Count = 2

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X