-2

I have a two classes. First (Spawn.cpp only prints the message that class was called):

// Spawn.h
#pragma once
#ifndef SPAWN_H_
#define SPAWN_H_
class Spawn {// const + destr only};
#endif /* SPAWN_H_ */

Second:

// Thread.h
#include "Spawn.h"
#pragma once
#ifndef THREAD_H_
#define THREAD_H_

class Thread
{
public:
    Thread();
    virtual ~Thread();

private:

    void Initialise();
    static int WindowThread(void *ptr);
    static int ConsoleThread(void *ptr);
    static Spawn * CreateSpawner();
    static Spawn * pSpawner; // if the pointer is non-static, it can't be
                             // used within static function.

    SDL_Thread * pConsoleThread;
};
Spawn * Thread::pSpawner = nullptr;
#endif /* THREAD_H_ */

The code itself:

// Thread.cpp
#include "stdafx.h"
#include "Thread.h"

Thread::Thread() { Initialise(); }

void Thread::Initialise() { // call of the threads here }


int Thread::WindowThread(void * ptr)
{
    while (true)
    {
        // I want to access pointer pSpawner here
    }
    return 1;
}


int Thread::ConsoleThread(void * ptr)
{
    // Main console loop
    while (true)
    {
        /* Spawn handling */
        if (CUI.INP == "spawn")
        {
            pSpawner = CreateSpawner(); // I am unable to access that
                                        // pointer here as well
        }
    }
    return 2;
}


Spawn * Thread::CreateSpawner()
{ 
    // Singleton initialisation:
    Spawn * m_pSPAWNER = new Spawn;
    return m_pSPAWNER;
}

I am using the SDL external library to create two threads, these threads are static int functions, so it's possible to use only static pointer (if I use a standard pointer the error is that the pointer must be static), but the error I get using Visual studio 2015:

Error LNK2001 unresolved external symbol "private: static class Spawn * Thread::pSpawner"

Error LNK1120 1 unresolved externals

I have tried the suggestions done here, but no result (you can find declaration and definition in the Thread.h): error LNK2001: unresolved external symbol public: static class

C++ vector issue - 'LNK2001: unresolved external symbol private: static...'

The answers from this question didn't helped (I will leave an update here when I will try all of the suggestions):

What is an undefined reference/unresolved external symbol error and how do I fix it?

Community
  • 1
  • 1
Pavel K
  • 13
  • 4
  • Please [edit] your question to provide a [mcve]. That's way to much code for a build time error like this. – Baum mit Augen Dec 07 '16 at 22:51
  • Search your code for the symbol `pt`. The linker is not finding it. The common idiom is to place the variable definition in a source file. – Thomas Matthews Dec 07 '16 at 22:55
  • Baum mit Augen, done. – Pavel K Dec 07 '16 at 22:59
  • Thomas Matthews, I am sorry, this a mistake, the error is with pSpawner, I changed edited the question. I tried to use a definition within the constructor, but still the same error. – Pavel K Dec 07 '16 at 23:00
  • Possible duplicate of [What is an undefined reference/unresolved external symbol error and how do I fix it?](http://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) – Ken White Dec 07 '16 at 23:03
  • Looked through that topic, tried to check the linker and possible reasons with proper header locations, but no result – Pavel K Dec 07 '16 at 23:32

1 Answers1

1
  1. This error message is pretty clear, you fail to define your global. It's better to define a global in a cpp file. Because with header he can be define each time you include the header.

    // Thread.cpp
    Spawn * Thread::pSpawner = nullptr;
    
  2. It's useless to use #pragma once and #ifndef. Do only one of them.

    #pragma once
    

    By the way if you use #ifndef ALL must be inside the #if. You have included "Spawn.h" outside, its can produce an infinite loop of include.

    "There is no advantage to use of both the #include guard idiom and #pragma once in the same file."

Stargateur
  • 24,473
  • 8
  • 65
  • 91
  • ***it's useless to use #pragma once and do a #ifndef do only one.*** I do that every time (thousands of times by now.). That way if I ever use a compiler that does not support pragma once the #ifndef will still do the trick.. if pragma once becomes part of the standard I will change my rule.. – drescherjm Dec 08 '16 at 00:04
  • @drescherjm That stupid, at least use `#if defined(_pragma_once_support)`. This pragma exist to win time, if you do a header guard too, you don't win time... – Stargateur Dec 08 '16 at 00:09
  • to be clear #2 fixes yr problem , #1 is a side issue – pm100 Dec 08 '16 at 00:20
  • @Stargateur: The reason `#pragma once` did not make it into the standard (at least yet) is that any modern preprocessor can easily be made smart enough to "win time" with header guards alone. I.e. I see how any problems with "winning time" can possibly be caused by header guards. – AnT stands with Russia Dec 08 '16 at 00:31
  • Hey guys, thanks for the answers. I've done as you said and now it works. I don't know why, but I was defining that pointer inside the constructor, but not at the start of the cpp file... some dark force.. – Pavel K Dec 08 '16 at 09:42
  • @PavelK If you put it in your constructor, it's will not be **define** the global. It's will **modify** each time the constructor is called. global need to be defined in the global scope. I don't understand how you even compile. By the way, that means that you lie in your question. Because you write it after the class declaration. Please don't do that again! How do you want us solve your problem if you don't provide the true code. It's very important to reduce your code, but don't change its behavior. – Stargateur Dec 08 '16 at 09:55
  • @Stargateur, no-no, I didn't lied, I just said, that I tried it before within the constructor. The code with initialization after the class declaration is correct at moment of posting the question. – Pavel K Dec 08 '16 at 11:09