執行緒的封裝很簡單,並沒有多少東西,但是如果我告訴你,我封裝的這個執行緒類裡有個成員函式start,作用是開啟執行緒執行,可以這樣呼叫:
class a
dword a::threadfunca(long lparam)
class b
dword b::threadfuncb(long lparam)
//呼叫**:
void a::startthread()
void b::startthread()
你是不是會覺得很神奇呢?a和b是完全不相干的兩個類,但其成員函式卻能作為引數傳進去。這個start並不是巨集,那其引數是怎麼定義的呢?
聰明的你一定已經想到模板了,不錯,這個start是乙個模板函式,但是呼叫時卻見不到模板呼叫時常見的***格式,並且呼叫的類,這個執行緒類產生物件時也不需要把具體資料型別傳入,這裡用到了一點技巧。
首先,想象一下這個start的實現機制,按執行緒實現的規則,一定是先把執行緒函式定位到乙個全域性或靜態的執行緒處理函式,然後由這個函式轉到具體的成員處理函式。這樣,這個函式就必須知道類a或b的成員函式指標,加上原來執行緒需要傳入的引數,因此傳入這個全域性執行緒處理函式的引數就必須是乙個結構了。定義一下這個結構:
template
struct threadinfo
;這個結構應該是作為cmythread的成員資料,由cmythread建立執行緒的時候作為引數傳給執行緒處理函式,對使用者是透明的。這時候問題來了,建立cmythread物件的時候必須初始化這個結構,但這時候還沒呼叫start,並不知道具體呼叫類的型別,而這個結構是必須關聯到具體資料型別的,cmythread初始化的時候這個結構該是什麼型別呢?這裡就要用到乙個資料型別強制轉換的技巧了,我們先宣告乙個空的類,拿這個類初始化這個結構:
class nullclass
;為了方便,typedef一下:typedef threadinfothinfo;
這個結構的型別就是:
class cmythread
;這裡額外提一下,在borland c++ 5.02下,這個nullclass只需要宣告,不需要實現,即可以不加{}:class nullclass;就行了,但是vc6就不行,加不加{},其sizeof(nullclass)返回的尺寸是不一樣的,加了{}返回的尺寸才是對的,不知是哪個公司錯了。
發現沒有,這個m_info結構裡有了乙個dword nullclass::threadfunc1)(long);函式指標,而這個nullclass根本沒有這個函式,沒關係,這個nullclass只是用來做資料型別轉換用,順帶也轉換了成員函式指標型別。為了方便,再typedef一下這個成員函式指標:typedef threadinfo::threadfunc1 threadfunc;
這樣這個start就能實現了:
class cmythread
...private:
static dword winapi threadproc(thinfo* obj);
private:
handle m_handle;
thinfo* m_info;
};threadproc就很簡單了:
dword winapi cmythread::threadproc(thinfo* obj)
這樣就可以象上面的**那樣呼叫:m_thread.start(this,(threadfunc)threadfunca);了,利用typename,把this指標傳遞進去,會自動判別資料型別,再利用nullclass作為資料型別轉換過個橋,這樣就實現任意類的成員函式指標傳遞了。而傳統的解決方法就需要在呼叫時多實現乙個全域性執行緒函式,傳遞this指標進去,再在全域性執行緒函式中得到這個指標呼叫成員函式,並沒實現真正的封裝。
C 中類的this指標以及const成員函式
類的基本思想 資料抽象和封裝。資料抽象依賴介面和實現分離的程式設計技術。類的設計者來思考類的實現過程。使用類的程式設計師只需要抽象的思考型別做了什麼。設計乙個類,就是乙個創造的過程。過程中需要考慮如何使得類易於使用。乙個優秀的類,既要有直觀易於使用的介面,也必須具備高效的實現過程。this是類額外的...
c 實現任意型別陣列類的封裝
myarray.hpp pragma once include includeusing namespace std templateclass myarray myarray const myarray array myarray 賦值操作符過載 防止淺拷貝 myarray operator my...
把類成員改成指標 C 帶有指標成員的類處理方式
在乙個類中,如果類沒有指標成員,一切方便,因為預設合成的析構函式會自動處理所有的記憶體。但是如果乙個類帶了指標成員,那麼需要我們自己來寫乙個析構函式來管理記憶體。在 中寫到,如果乙個類需要我們自己寫析構函式,那麼這個類,也會需要我們自己寫拷貝建構函式和拷貝賦值函式。析構函式 我們這裡定義乙個類has...