c++實現的委託機制(1)
1.引言
下面的委託實現使用的mygui裡面的委託實現,mygui是一款強大的gui庫,想理解更多的mygui資訊,猛擊這裡
// 普通函式
void normalfunc()
class base
};int main()
2.實現無參函式委託
要實現委託,首先要解決的是封裝c++中的函式指標。因為在c++中,普通函式指標和類成員函式指標是完全不一樣的。如下例子
class cmyclass
;// 定義乙個指向cmyclass型別,引數列表為(int),返回值為void的函式指標
typedef void (cmyclass::*classmethod) (int); // 注意定義時使用了特殊的運算子::*
那麼此函式指標只能指向cmyclass型別的成員函式,不能指向其他類或者普通函式
類成員函式指標不能直接呼叫,要通過乙個類例項來呼叫,如下
cmyclass *object = new cmyclass;
classmethod method = cmyclass::func;
(object->*method)(5); // 注意呼叫時使用了特殊運算子->*
那麼如何封裝呢?我們先來定義下介面吧
(為了簡單起見,下面的實現都是以無參函式為例,後續會講到如何支援任意引數)
class idelegate
virtual bool istype(const std::type_info& _type) = 0;
virtual void invoke() = 0;
virtual bool compare(idelegate *_delegate) const = 0;
};
idelegate類的介面很少,也很簡單,必要介面只有乙個,就是invoke,用於觸發函式
但為了可以方便管理,使用了istype和compare函式來進行相等判斷。
下面是封裝的普通函式指標
class cstaticdelegate : public idelegate
virtual bool istype( const std::type_info& _type)
virtual void invoke()
virtual bool compare(idelegate *_delegate) const
private:
func mfunc;
};
可以看到,cstaticdelegate只是簡單地封裝了普通函式指標,**也非常簡單
(類的某些成員函式,如istype和compare使用了rtti,
對c++的動態型別判斷不熟的可以猛擊這裡
好了,注意了,下面開始封裝類成員函式指標
templateclass cmethoddelegate : public idelegate
virtual bool istype( const std::type_info& _type)
virtual void invoke()
virtual bool compare(idelegate *_delegate) const
private:
t * mobject;
method mmethod;
};
首先解釋一下:因為類成員函式指標與類的型別有關,不同類的成員函式指標是不一樣的。
要解決型別不同,很簡單,使用模板就行。
**跟cstaticdelegate基本一樣,下面稍微解釋一下:
cmethoddelegate類主要封裝了乙個類例項指標以及類成員函式的指標
這樣在invoke時就不要額外的通過乙個類例項了
要注意一點,compare函式的實現中,相等判定是類例項以及類函式指標都一樣。
也就是說就算是指標同乙個成員函式,但例項不同,委託就不同
為了方便使用,定義函式newdelegate來建立委託使用的函式
inline idelegate* newdelegate( void (*_func)() )
templateinline idelegate* newdelegate( t * _object, void (t::*_method)() )
至此,對c++函式指標的封裝就完成了,不難吧。
下面就是委託的實現了
class cmultidelegate
~cmultidelegate ()
bool empty() const
return true;
}void clear()}}
cmultidelegate& operator+=(idelegate* _delegate)
}mlistdelegates.push_back(_delegate);
return *this;
}cmultidelegate& operator-=(idelegate* _delegate)
}delete _delegate;
return *this;
}void operator()( )
else}}
private:
cmultidelegate (const cmultidelegate& _event);
cmultidelegate& operator=(const cmultidelegate& _event);
private:
listdelegate mlistdelegates;
};
仔細理解下cmultidelegate類的實現,**都不深奧。
比較重要的是3個函式 :+=,-=,()運算子的過載函式
+= 用於新增乙個委託函式
-= 用於去掉乙個委託函式
() 用於觸發委託函式
差不多就是普通的stl容器使用了。
這裡要重點說明的一點是,大家仔細看 += 函式的實現中
if ((*iter) && (*iter)->compare(_delegate))
為什麼要delete掉外部的指標呢?
因為c++的記憶體洩露一直是個麻煩事,所以myugi的委託裡,所有的委託函式統一由delegate本身管理
外部不要自己new或delete委託函式,也不要儲存乙個委託函式,delegate本身會管理好的。
建議像如下使用:
cmultidelegate mydelegate;
mydelegate += newdelegate(normalfunc);
mydelegate -= newdelegate(normalfunc);
而不建議像如下使用:
cmultidelegate mydelegate;
idelegate* delegatefunc = newdelegate(normalfunc);
mydelegate += delegatefunc;
mydelegate -= delegatefunc;
上面2種方法都沒錯,都不會造成記憶體洩露
你可能會覺得第2種方法減少new的次數,比第一種方法更好。其實不然,因為第2種方法有個很大的隱患
mydelegate -= delegatefunc; // 在這一步,delegatefunc所指向的空間已經被釋放掉了(在-=函式裡面)
所以如果你後面又想將delegatefunc新增到mydelegate裡面時,你就不能再這樣用了
mydelegate += delegatefunc; // 錯誤,因為delegatefunc的空間已經被釋放了
你得重新new乙個
delegatefunc = newdelegate(normalfunc);
mydelegate += delegatefunc;
相信你不會願意這樣做的,因為這種方法很容易造成記憶體洩露或者崩潰
現在你應該可以明白 -= 函式是怎麼釋放委託函式記憶體了吧。
C 實現的委託機制(一)
c 實現的委託機制 一 1.引言 下面的委託實現使用的mygui裡面的委託實現,mygui是一款強大的gui庫,想理解更多的mygui資訊,猛擊這裡 我們的目標是要實現乙個跟.net幾乎完全一樣的委託,使用簡單,支援多播,可以新增刪除委託。同時支援c 的普通函式 模板函式 類成員函式,類的靜態成員函...
C 實現的委託機制(二)
c 實現的委託機制 二 1.實現任意引數的函式委託 只能不同個數各實現乙個類,如 單參函式委託 templateclass cmultidelegate1 雙參函式委託 templateclass cmultidelegate2 注意類名是不一樣的,分別為cmultidelegate1和cmulti...
C 委託機制
c 的委託機制,實際上相當於函式的指標。如下例項 1 定義乙個類 class person string name public void person this.name name private virtual void eat food food 在該類中定義了乙個eat方法。對該物件進行例項...