C 實現的委託機制 1

2021-05-28 16:29:47 字數 4179 閱讀 1040

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方法。對該物件進行例項...