2011-08-24 121 views
1

我可以使用成員函數中的線程在Windows中爲C++調用成員函數嗎?如果是的話,如何實施呢?下面是示例成員函數中的C++線程

void Class::fun_1(void){ 
_beginthread(fun_2, 0, NULL); //This is the error line :: function call missing argument list; use '&Class::fun_2' to create a pointer to member 
} 

void Class::fun_2(void){ 
printf("hello"); 
} 

感謝

+1

什麼是_beginthread? –

+1

@Nicol Bolas,'_beginthread'是一個叫做'win32'的黑暗世界的功能。 http://msdn.microsoft.com/en-us/library/kdzttdcb(v=vs.80).aspx –

+0

@Nicol Bolas:http://msdn.microsoft.com/en-us/library/kdzttdcb.aspx –

回答

7

實際上有多個問題在這裏:

  1. 您可以將指針不能傳遞給一個成員函數作爲該過程移至_beginthread()功能。該函數需要一個指向全局或靜態函數的指針。
  2. 標準C++要求您完全限定成員函數名稱(甚至在類中)並使用&來獲取指向該成員的指針(編譯器正在向您抱怨這一點)。

因爲無法將成員函數指針傳遞給_beginthread(),所以需要創建一個包裝器全局或靜態函數來使其工作。下面是做到這一點的一種方式:

class MyClass 
{ 
public: 
    void fun_1() 
    { 
     _beginthread(&MyClass::fun_2_wrapper, 0, static_cast<void*>(this)); 
    } 

private: 
    void fun_2() 
    { 
     printf("hello"); 
    } 

    static void __cdecl fun_2_wrapper(void* o) 
    { 
     static_cast<MyClass*>(o)->fun_2(); 
    } 
}; 

當然,你需要以某種方式保證MyClass對象將仍然是長期存在的fun_2()運行,或者不那麼好的事情會發生。如果你不用擔心它,可以考慮使用Boost.Thread,它基本上可以爲你做更多的事情。

+0

如果fun_2將訪問一些私人蔘數,例如,void fun_2(){charString =「abc」; // charString是Class的私有成員},那麼對於fun_2,這不是一個成員函數。它能夠直接訪問嗎? – Ian

+0

@Ian:'fun_2()'應該仍然可以訪問類成員,因爲'fun_2()'仍然是'MyClass'的成員函數。 'fun_2_wrapper()'是否有'_beginthread()'可以調用你的線程例程。 –

5

通常的做法是使用靜態成員函數,該函數使用指向原始對象的void指針調用成員函數。

class Class 
{ 
public: 
    void fun_1(void) 
    { 
     _beginthread(&Class::static_fun_2, 0, this); 
    } 
    void fun_2(void) 
    { 
     printf("hello"); 
    } 
private: 
    static void static_fun_2(void * args) 
    { 
     static_cast<Class*>(args)->fun_2(); 
    } 

}; 

但是,如果你開始需要傳遞參數給這些函數,事情會變得更復雜一點。我會看看使用boost :: thread和boost :: bind來代替滾動你自己的。

+0

您可以直接使用'boost :: bind'或'std :: bind'作爲'_beginthread',從而跳過對靜態函數的需求嗎? – User

+0

@User我不認爲你可以直接使用綁定,因爲你將參數傳遞給'_beginthread',它需要是某種函數類型。不過,你可以用'boost :: thread'的風格爲'_beginthread'創建一個包裝器,它將接受更多的通用函數 - 允許你使用bind。 –