昨天用C++把我寫的一個游戲功能進行了封裝,其中涉及到一個小問題,就是我封裝的C++類中必須定義2個線程函數,比如像下面這樣:
1. class A
2. {
3. public:
4. A();
5. ~A();
6.
7. void XXX(void *p); //此函數為線程回調函數
8. };
其中XXX為線程回調函數,在另一個線程啟動函數中需要用_beginthread()這個函數來調用的。但是當我在這麼寫時:
_beginthread(XXX, 0, NULL);
編譯器報錯誤。。也就是無法編譯通過。我仔細想了想,覺得確實也無法編譯通過,因為線程函數在編譯的時候必須知道函數入口地址才行,而我這麼寫,XXX的入口地址確實還是未知的。。
所以我想到了兩種把未知變為已知的方法,一種是把XXX定義成靜態成員函數,如下:
static void XXX(void *p);
另一種是把XXX定義成全局函數。
其實是一個道理,就是為了讓_beginthread()知道這個函數的入口地址,全局函數和靜態函數都存放在一個地方,在編譯時都是已知的。
當我以為一切OK的時候,發現在XXX()函數中又報錯了。。
說我使用了不在類域中的成員。其實就是這麼個意思:
1. class A
2. {
3. public:
4. A();
5. ~A();
6.
7. static void XXX(void *p); //此函數為線程回調函數www.2cto.com
8.
9. int a; //在XXX函數中會進行修改
10. };
其中A的成員變量a會在XXX()函數中進行修改,而在XXX函數中其實是看不到這個成員的。
你也許會問,怎麼就看不到呢?我平時就是這麼寫的啊。比如我在A中定義的其他成員函數就可以直接訪問這個a啊。
確實,在類A中其他的一般成員函數是可以訪問這個成員變量a的。但是我們很容易忽略了一點,就是在一般成員函數中其實有一個隱藏的參數,就是指向這個類的this指針,我們在成員函數中訪問成員變量a,其實是在訪問this->a。所以我們的成員函數能夠找到這個a,而我們的線程函數卻沒有傳遞這個參數,XXX()是用_beginthread()函數來創建的,所以如果我們要給XXX()傳遞參數,就必須寫在_beginthread()的第三個參數中,可以看到我上面寫的第三個參數是NULL,所以在XXX()中是無法訪問成員變量a的,因為沒有this指針。
明白這一點以後就非常容易了,在_beginthread()中把this指針傳遞給XXX()函數,然後在XXX()函數中把void*類型轉換成類A的指針就可以了。如下:
1. class A
2. {
3. public:
4. A();
5. ~A();
6.
7. static void XXX(void *p); //此函數為線程回調函數
8. void start(); //線程啟動函數
9. int a; //在XXX函數中會進行修改
10. };
11.
12. void start()
13. {
14. _beginthread(XXX, 0, this);
15. }
16.
17. void XXX(void *p)
18. {
19. A *handle = (A *)p;
20. int b = handle->a;
21. }
我是不是很牛。。。呵呵。好吧,我泛濫了。
摘自 菜鳥浮出水