Símbolo externo não resolvido nos membros da classe estática

129

Muito simplesmente:

Eu tenho uma classe que consiste principalmente de membros públicos estáticos, para que eu possa agrupar funções semelhantes que ainda precisam ser chamadas de outras classes / funções.

De qualquer forma, eu defini duas variáveis ​​estáticas de caracteres não assinadas no escopo público da classe. Quando tento modificar esses valores no construtor da mesma classe, estou recebendo um erro "símbolo externo não resolvido" na compilação.

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

    ...

    test();
};

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

Eu sou novo em C ++, então vá com calma comigo. Por que não posso fazer isso?

AustinWBryan
fonte

Respostas:

145

Você esqueceu de adicionar as definições para corresponder às suas declarações de X e Y

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

algum lugar. Você também pode querer inicializar um membro estático

unsigned char test::X = 4;

e novamente, você faz isso na definição (geralmente em um arquivo CXX) e não na declaração (que geralmente está em um arquivo .H)

Colin Jensen
fonte
4
Se você estiver escrevendo biblioteca somente cabeçalho, você pode usar esta técnica para evitar arquivo cpp: stackoverflow.com/questions/11709859/...
Shital Shah
62

Declarações de membros de dados estáticos na declaração de classe não são uma definição deles. Para defini-los, você deve fazer isso no .CPParquivo para evitar símbolos duplicados.

Os únicos dados que você pode declarar e definir são constantes estáticas integrais. (Os valores de enumspodem ser usados ​​também como valores constantes)

Você pode reescrever seu código como:

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

test::test() {
}

Se você deseja modificar suas variáveis ​​estáticas (em outras palavras, quando é inapropriado declará-las como const), você pode separar seu código entre .He .CPPda seguinte maneira:

.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
fonte
por que aqui em .CPP, é "char char test: X = 1;" em vez de "test :: X = 1;"? variável estática X já definida, por que ainda precisa de "char não assinado"? @sergtk
Penny
@ Penny Porque "test :: X = 1;" é interpretado como uma tarefa, enquanto o que estamos tentando fazer é uma definição.
Anonymous1847
4

Como esse é o primeiro thread SO que pareceu surgir para mim ao procurar por "externos não resolvidos com membros const estáticos" em geral, deixarei outra dica para resolver um problema com externos não resolvidos aqui:

Para mim, o que esqueci foi marcar minha definição de classe __declspec(dllexport)e, quando chamado de outra classe (fora dos limites da DLL da classe), é claro que recebi o meu erro externo não resolvido.
Ainda assim, é fácil esquecer quando você está mudando uma classe auxiliar interna para uma classe acessível de outro lugar; portanto, se você estiver trabalhando em um projeto vinculado dinamicamente, também poderá verificar isso.

Johann Studanski
fonte
2

no meu caso, declarei uma variável estática no arquivo .h, como

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

e no myClass.cpp, tentei usar esse m_nMyVar. Obteve erro de LINK como:

erro LNK2001: símbolo externo não resolvido "public: static class ... O arquivo cpp relacionado ao erro de link é semelhante a:

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

Então, adiciono o código abaixo na parte superior do 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
}

então o LNK2001 se foi.

Centavo
fonte
0

No meu caso, eu estava usando um link errado.
Foi gerenciado c ++ (cli), mas com exportação nativa. Eu adicionei ao vinculador -> entrada -> recurso de link de montagem a dll da biblioteca da qual a função é exportada. Mas a vinculação nativa em c ++ requer que o arquivo .lib "veja" as implementações no cpp corretamente, então, para mim, ajudei a adicionar o arquivo .lib ao vinculador -> entrada -> dependências adicionais.
[Normalmente, o código gerenciado não usa exportação e importação de DLL, ele usa referências, mas essa era uma situação única.]

whats_wrong_here
fonte