Simbolo esterno non risolto sui membri di classe statici


129

In parole povere:

Ho una classe che consiste principalmente di membri pubblici statici, quindi posso raggruppare funzioni simili che devono ancora essere chiamate da altre classi / funzioni.

Comunque, ho definito due variabili statiche senza segno statiche nel mio ambito pubblico di classe, quando provo a modificare questi valori nel costruttore della stessa classe, ricevo un errore "simbolo esterno non risolto" durante la compilazione.

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

    ...

    test();
};

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

Sono nuovo di C ++ quindi andate piano con me. Perché non posso farlo?

Risposte:


145

Hai dimenticato di aggiungere le definizioni per abbinare le tue dichiarazioni di X e Y

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

da qualche parte. Potresti voler inizializzare anche un membro statico

unsigned char test::X = 4;

e ancora, lo fai nella definizione (di solito in un file CXX) non nella dichiarazione (che spesso si trova in un file .H)


4
Se si sta scrivendo biblioteca intestazione-only, è possibile utilizzare questa tecnica per evitare di file cpp: stackoverflow.com/questions/11709859/...
Shital Shah

62

Le dichiarazioni dei membri di dati statici nella dichiarazione di classe non ne sono la definizione. Per definirli dovresti farlo nel .CPPfile per evitare simboli duplicati.

Gli unici dati che è possibile dichiarare e definire sono costanti statiche integrali. (I valori di enumspossono essere usati anche come valori costanti)

Potresti voler riscrivere il tuo codice come:

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

test::test() {
}

Se si desidera avere la possibilità di modificare le variabili statiche (in altre parole quando non è appropriato dichiararle come const), è possibile separare il codice tra .He .CPPnel modo seguente:

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

perché qui in .CPP, è "char char unsigned :: X = 1;" invece di "test :: X = 1;"? variabile statica X già definita, perché è ancora necessario "carattere senza segno"? @sergtk
Penny,

@Penny Perché "test :: X = 1;" viene interpretato come un incarico, mentre quello che stiamo cercando di fare è una definizione.
Anonimo1847

4

Dal momento che questo è il primo thread SO che mi è apparso durante la ricerca di "esterni non risolti con membri const statici" in generale, lascerò un altro suggerimento per risolvere un problema con gli esterni non risolti qui:

Per me, la cosa che ho dimenticato era di contrassegnare la definizione della mia classe __declspec(dllexport)e, quando chiamato da un'altra classe (al di fuori dei limiti della dll di quella classe), ovviamente ho ricevuto il mio errore esterno irrisolto.
Tuttavia, è facile dimenticare che quando si cambia una classe di supporto interna in una classe accessibile da un'altra, quindi se si lavora in un progetto collegato dinamicamente, è possibile verificarlo anche.


2

nel mio caso, ho dichiarato una variabile statica nel file .h, come

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

e in myClass.cpp, ho provato ad usare questo m_nMyVar. Ha ottenuto un errore LINK come:

errore LNK2001: simbolo esterno non risolto "pubblico: classe statica ... Il file cpp relativo all'errore di collegamento è simile a:

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

Quindi aggiungo sotto il codice nella parte superiore di 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
}

quindi LNK2001 non c'è più.


0

Nel mio caso, stavo usando un collegamento sbagliato.
È stato gestito in c ++ (cli) ma con esportazione nativa. Ho aggiunto al linker -> input -> assembly link resource la dll della libreria da cui viene esportata la funzione. Ma il collegamento c ++ nativo richiede che il file .lib "veda" le implementazioni in cpp correttamente, quindi per me ho aiutato ad aggiungere il file .lib al linker -> input -> dipendenze aggiuntive.
[Di solito il codice gestito non usa l'esportazione e l'importazione della dll, usa riferimenti, ma quella era una situazione unica.]

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.