2011-01-12 5 views
5

Wie der Titel sagt. Das folgende ist mein Code-Skelett.führen Sie Threads der Klassenmitgliedsfunktion in C++

class CLASS 
{ 
public: 
    void A(); 
private: 
    DWORD WINAPI B(LPVOID); 
}; 

void CLASS::A() 
{ 
    DWORD (WINAPI CLASS::*thread)(LPVOID) = &CLASS::B; 
    ... 
    CreateThread(NULL, 0, thread, &arg, 0, NULL); 
    ... 
} 

Die Funktion B benötigt CLASS-Member-Variablen.
Aber ich habe einen Fehlercode, als ich das kompiliert habe.
Es ist "kann nicht konvertieren Argument 3 von" DWORD (__stdcall CLASS :: *) (LPVOID) "zu" LPTHREAD_START_ROUTINE "oder so ähnlich.
Ich weiß nicht, ob es in der englischen Umgebung gleich ist.

kann jemand bitte helfen?

Antwort

3

Sie müssen diese Elementfunktion static machen. Das Problem hier ist, dass jede nicht-statische Member-Funktion einen impliziten this Parameter hat und das ist genau das, was der Compiler Ihnen zu sagen versucht - Ihre nin-statische Member-Funktion hat eine Signatur, die sich von der erwarteten unterscheidet.

Siehe auch this answer to a closely related question.

+3

und vor der OP beginnt Irgendwelche cleveren Ideen bekommen - nicht statische Klassenmitgliedsfunktionszeiger sind * seltsam *. Die Aufrufkonventionen unterscheiden sich nicht nur von einem einfachen 'func (Klassenname * this, ...)', die Zeigerdarstellung ist seltsam - in einigen Fällen können Klassenelementfunktionszeiger die doppelte Größe eines normalen Funktionszeigers haben Denken Sie nicht einmal daran, die Besetzung zu zwingen :) – bdonlan

10

Sie müssen Ihre Callback-Funktion als static Funktion definieren, wenn es Mitgliedfunktion ist!


Besseres Design: Definieren Sie eine wiederverwendbare Klasse!

Aus meinem previous answer: (mit wenig Modifikation)

Noch besser wäre es, eine wiederverwendbar Klasse mit rein virtueller Funktion zu definieren run() von den abgeleiteten Thread Klassen implementiert werden. Hier ist, wie sollte es gestaltet sein:

//runnable is reusable class. All thread classes must derive from it! 
class runnable 
{ 
public: 
    virtual ~runnable() {} 
    static DWORD WINAPI run_thread(LPVOID args) 
    { 
     runnable *prunnable = static_cast<runnable*>(args); 
     return prunnable->run(); 
    } 
protected: 
    virtual DWORD run() = 0; //derived class must implement this! 
}; 

class Thread : public runnable //derived from runnable! 
{ 
public: 
    void newthread() 
    { 
     CreateThread(NULL, 0, &runnable::run_thread, this, 0, NULL); 
    } 
protected: 
    DWORD run() //implementing the virtual function! 
    { 
     /*.....your thread execution code.....*/ 
    } 
} 
+0

Ich würde eine Vorlage verwenden, anstatt Laufzeitvererbung. Aber die allgemeine Idee ist richtig. – Puppy

+0

@DeadMG: meinst du CRTP? – Nawaz

+0

+1, aber ich würde die 'run' Methode geschützt machen. –

11

Ernsthaft Verwendung std :: Thread (oder boost :: Thread, wenn Ihr Compiler es noch nicht unterstützt):

class CLASS 
{ 
public: 
    void A(); 
private: 
    void B(your args go here); 
}; 

void CLASS::A() 
{ 
    boost::thread(&CLASS::B, this, your args go here); 
} 
+2

+1. Ja, gehen Sie definitiv mit std ::/boost :: thread. Außerdem brauchst du nicht einmal bind: 'boost :: thread (& CLASS :: B, das sind deine Argumente falls hier);'. So einfach ist das. – usta

+0

@usta: danke! Fest. – ybungalobill