2013-12-14 142 views
6

我有一個類播放器,並且一些子類Player1,Player2,Player3使用C++擴展播放器。
類播放器有一個「運行」的方法,所有Player1,2,3將覆蓋「運行」做不同的事情。
如何在實例方法中使用C++ 11線程?

class Player { 
public: 
    virtual void run(); 
} 
class Player1: public Player { 
public: 
    void run(); 
} 

在「主」的功能,我將創建Player1,2,3
的一些實例,這些實例的一些C++ 11線程調用方法「運行」。

int main() { 
    Player1 player1; 
    Player2 player2; 
    Player3 player3; 
    Thread thread1(player1.run, this); 
    Thread thread2(player2.run, this); 
    Thread thread3(player3.run, this); 
    thread1.join(); 
    thread2.join(); 
    thread3.join(); 

    return 0; 
} 

我都試過,我知道這是行不通的,
所以我嘗試用另一個函數來調用實例方法。

function doRun1(Player1 player){ 
    player.run(); 
} 

int main() { 
    Player1 player1; 
    Player2 player2; 
    Player3 player3; 
    Thread thread1(doRun1, player1); 
    Thread thread2(doRun2, player2); 
    Thread thread3(doRun3, player3); 
    thread1.join(); 
    thread2.join(); 
    thread3.join(); 

    return 0; 
} 

這樣似乎解決問題,但我要創建doRun1,doRun2,doRun3 ....大量的功能,
因爲doRun1,2,3的參數需要被宣告這是PLAYER1 ,2或3

我想不出還有什麼更好的解決辦法,有人可以幫我@@?

+5

C11與此有什麼關係? 「Thread」究竟是什麼,那個構造函數的簽名是什麼? – Mat

+0

哇。 C11也有課嗎? – juanchopanza

+0

對不起,我的錯......我知道@@是什麼問題。我的意思是C++ 11不是C11,我會糾正它...原諒我 –

回答

12

您正在尋找這樣的事情...

class Player { 
public: 
    virtual void run() = 0; 
}; 

class Player1: public Player { 
public: 
    void run(); // you must implement then for Player1, 2, 3 
}; 

void doRun(Player * player) 
{ 
    player->run(); 
} 

int main(int argc, char * argv[]) { 
    Player1 player1; 
    Player2 player2; 
    Player3 player3; 

    thread thread1(doRun, &player1); 
    thread thread2(doRun, &player2); 
    thread thread3(doRun, &player3); 

    thread1.join(); 
    thread2.join(); 
    thread3.join(); 

    return 0; 
} 

如果你願意,你也可以使用lambda表達式:

int main(int argc, char * argv[]) { 
    Player1 player1; 
    Player2 player2; 
    Player3 player3; 

    thread thread1([&] (Player * player) { player->run(); }, &player1); 
    thread thread2([&] (Player * player) { player->run(); }, &player2); 
    thread thread3([&] (Player * player) { player->run(); }, &player3); 

    thread1.join(); 
    thread2.join(); 
    thread3.join(); 

    return 0; 
} 

或者,下面DYP建議:

int main(int argc, char * argv[]) { 
    Player1 player1; 
    Player2 player2; 
    Player3 player3; 

    thread thread1(&Player::run, player1); 
    thread thread2(&Player::run, player2); 
    thread thread3(&Player::run, player3); 

    thread1.join(); 
    thread2.join(); 
    thread3.join(); 

    return 0; 
} 
+4

值得一提的是,這些線程可以在'player1','player2','player3'的副本*上運行。如果需要引用語義,'std :: reference_wrappers'是一個很好的選擇(傳遞'std :: ref(player1)'等)。另外,'main'應該返回'int'。 – juanchopanza

+0

感謝您的解決方案!我會嘗試 –

+3

爲什麼不只是'thread thread1(&Player :: run,player1);'? (指向虛擬成員函數的指針仍然允許動態調度。) – dyp

3

你實際上尋找的是std::bind

#include <thread> 
#include <functional> 

using namespace std; 

void main() 
{ 
    Player1 myPlayer1; 

    thread thread1(bind(&Player1::run, &myPlayer1)); 
} 

你正在做的是創建一個std::function對象,thread構造函數接受該對象。然後,您將作爲bind函數的一部分「烘焙」實例。但是要真正小心這一點,就像myPlayer1超出範圍時那樣,指針也是如此。有時,您可能希望這樣:

#include <thread> 
#include <functional> 
#include <memory> 

using namespace std; 

void main() 
{ 
    shared_ptr<Player1> ptr_myPlayer1(new Player1()); 

    thread thread1(bind(&Player1::run, ptr_myPlayer1)); 
} 

這使得對象的生命週期是線程的生命週期,而不是main壽命。在你的微不足道的例子中,這不是一個問題,但這是現實生活中的一個問題。

查看here欲瞭解更多關於綁定的信息,請閱讀functional的全部內容。

編輯:

什麼結合上面有關動態調度說,這也是可能的:

#include <thread> 
#include <memory> 

using namespace std; 

void main() 
{ 
    shared_ptr<Player> ptr_myPlayer(new Player1()); // Works because holds a pointer to base class 

    thread thread1(&Player::run, ptr_myPlayer1); 
} 

您使用的基類的虛函數這樣,但你使用一個指向子類實例的智能指針,所以你可以退出原始函數(假設不​​是主要的,程序沒有結束)。最好的世界。bind在這裏沒有必要(因爲std::thread已經在內部執行這個操作,至少這是一個可能的實現),但它仍然是OP所需的「函數指向任何東西」的總體思路。