Undefinied reference zu static membern

FBIagent

Erfahrenes Mitglied
Moin,

ich habe folgendes:

Ich möchte in einer Klasse mit "CreateThread" einen Thread starten. Dabei musste ich
allerdings feststellen das die Threadfunktion static sein muss. Ok gesagt getan,
habe ich sie static gemacht und die Variablen die die Threadfunktion benutzt auch.
Nur bekome ich nun einige Fehler beim kompilieren. Die Threadfunktion greift auf
static Variablen in der Klasse zurück und da bin ich auch schon bei den Fehlern.
Code:
Undefinied reference to ""...

Folgender Code:
C++:
class test
{
    static int x, y;
    static std::string text;

    static DWORD WINAPI run(LPVOID data)
    {
        std::cout << x << y << "\n";
        std::cout << text;

        return (DWORD)data;
    }
private:
    bool wait;
public:
    void start(int xStart, int yStart, std::string textStart, bool waitStart)
    {
        x = xStart;
        y = yStart;
        text = textStart;
        wait = waitStart;
        hThread = CreateThread(NULL, 0, run, (LPVOID)0, 0, &dwThreadId);

        if (wait)
            WaitForSingleObject(hThread, INFINITE);
    }

};

Oder liegt es gar an "start(int,int,std::string,bool)", weil sie die nicht static ist?
 
Zuletzt bearbeitet von einem Moderator:
Hallo,

FBIagent hat gesagt.:
Code:
Undefinied reference to ""...
Warum verrätst du uns denn nicht die komplette Fehlermeldung? Solange wir nicht wissen, an welcher Stelle der Fehler auftritt, können wir leider nur raten…

Es könnte aber helfen, wenn du im Aufruf von CreateThread das run durch test::run ersetzt.

Grüße,
Matthias
 
Also die fehlermeldungen waren wie folgt:

Code:
    Undefinied reference to test::x
    Undefinied reference to test::y
    Undefinied reference to test::text

Habe noch ein bischen nach Threading informationen gegoogled bin auf so manchen
Beispielcode gestoßen habe mich über die einzelnen Befehle informiert und mir daraus
dann eine ganz kleine Threading class geschrieben.
Zum starten eines Threads habe ich nun 3 Methoden:
C++:
bool thread::start();
static DWORD WINAPI starting();
virtual void run();  // muss in jedem fall überschrieben werden

start(); startet starting(); als Thread, der Thread widerum ruft mit einem Pointer zur Klasse
selbst die überschriebene run methode auf... aber siehe selbst:

C++:
#################
# thread.h             #
#################
#ifndef MY_THREAD_H
#define MY_THREAD_H

#include <windows.h>

class thread
{
	static DWORD WINAPI starting(LPVOID data)
	{
		thread *pointerThis = static_cast<thread*>(data);

		if(pointerThis != NULL)
			pointerThis->run();

        return (DWORD)data;
	}

protected:
	DWORD dwThreadId;
	HANDLE hThread;
	HANDLE hStopEvent;
    bool paused;

	bool testStop()
    {
        return(::WaitForSingleObject(hStopEvent, 0) == WAIT_OBJECT_0);
    };

	virtual void run() = 0;

public:
	thread();
	virtual ~thread();

    bool isRunning();

	bool start();
    bool pause();
    bool resume();
    bool waitAndStop();
};

#endif

#################
# thread.cpp          #
#################
#include ".\thread.h"

thread::thread()
{
    hThread = NULL;
    hStopEvent = NULL;
    dwThreadId = 0;
    paused = false;
}

thread::~thread()
{
	waitAndStop();
}

bool thread::isRunning()
{
	DWORD dwExitCode = 0;
	GetExitCodeThread(hThread, &dwExitCode);
	return (dwExitCode == STILL_ACTIVE);
}

bool thread::start()
{
	if(isRunning())
		return false;

	hStopEvent = ::CreateEvent(NULL, true, false, NULL);

	if(hStopEvent == NULL)
		return false;

	DWORD ThreadId;
	hThread = ::CreateThread(NULL, 0, starting, this, 0, &ThreadId);

	if(hThread == NULL)
		return false;

	dwThreadId = ThreadId;

	return true;
}

bool thread::pause()
{
    if (!paused)
    {
        ::SuspendThread(hThread);
        paused = true;
        return true;
    }

    return false;
}

bool thread::resume()
{
    if (paused)
    {
        ::ResumeThread(hThread);
        paused = false;
        return true;
    }

    return false;
}

bool thread::waitAndStop()
{
	if(::SetEvent(hStopEvent))
	{
		::WaitForSingleObject(hThread, INFINITE);
		::CloseHandle(hThread);
		::CloseHandle(hStopEvent);
		return true;
	}

	return false;
}

Beispielcode zum benutzen der Klasse(ein kleiner laufext ;) ):
C++:
#################
# runningText.h      #
#################
#ifndef RUNINGTEXT_H
#define RUNNIGTEXT_H

#include <iostream>
#include <string>

#include ".\console.h"
#include ".\thread.h"

class runningText : public thread, console
{
private:
    int x, y, interval;
    std::string text;
public:
    runningText(int,int,std::string,int);

    void run();
};

#endif

#################
# runningText.cpp  #
#################
#include ".\runningText.h"

runningText::runningText(int xConstr, int yConstr, std::string textConstr, int intervalConstr)
{
    x = xConstr;
    y = yConstr;
    text = textConstr;
    interval = intervalConstr;
}

void runningText::run()
{
    int wrap = 0;

    gotoXY(x, y);

    for (int i=0;i<text.length();i++)
    {
        Sleep(interval);

        if (text.substr(i,1) == "\n")
        {
            wrap++;
            gotoXY(x, y+wrap);
        }
        else
            std::cout << text.substr(i,1);
    }
}

#################
# main.cpp            #
#################
#include ".\runningText.h"

runningText runTxt(10,1,"LaLeLu\nLaLeLu\nLaLeLu\nLaLeLu\nLaLeLu\nLaLeLu\nLaLeLu\nLaLeLu\n",100);

int main()
{
    runTxt.start();
    runTxt.waitAndStop();
    system("Pause");

    return 0;
}

MFG FBIagent

EDIT:
Ohhh.... da hab ich glatt die console Klasse vergessen:
C++:
#################
# console..h          #
#################
#ifndef MY_CONSOLE_H
#define MY_CONSOLE_H

#include <iostream>
#include <windows.h>

class console
{
public:
  void gotoXY(int,int);
  void setColor(int);
  void clear();
  void clearLine(int);
};

#endif

#################
# console..cpp       #
#################
#include ".\console.h"

void console::gotoXY(int x,int y)
{
  HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE);
  COORD pos;
  pos.X=x;
  pos.Y=y;
  SetConsoleCursorPosition(hCon, pos);
}

void console::setColor(int color)
{
  HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE);
  SetConsoleTextAttribute(hCon,color);
}

void console::clear()
{
  gotoXY(0, 0);

  for (int y=0;y<25;y++)
  {
    for (int x=0;x<80;x++)
      std::cout << " ";
  }
  
  gotoXY(0, 0);
}

void console::clearLine(int line)
{
  gotoXY(0, line);
  
  for (int x=0;x<80;x++)
      std::cout << " ";
}
 
Zuletzt bearbeitet von einem Moderator:
Die static-Variablen müssen explizit initialisiert werden (im .cpp, außerhalb von Methoden):
C++:
int test::x            = 0;
int test::y            = 0;
std::string test::text = "";
Gruß
MCoder
 
Zurück