C++實現的委託機制(三)

來源:互聯網
上載者:User

C++實現的委託機制(三)

作者:gouki04(啊古)  撰寫日期:2011-10-08

部落格連結:http://blog.csdn.net/gouki04

1.引言

按上一篇文章的方法,你已經可以使用任意參數的函數委託了。這裡介紹下MyGUI實現的兩個輔助類,CDelegate類和IDelegateUnlink。如果你不為了深入瞭解MyGUI的委託實現,可以跳過此處。CDelegate即為單委託,實際效果跟函數指標差不多,於CMultiDelegate的區別在於其不支援多播。而IDelegateUnlink類主要是在CMultiDelegate中使用,在多播下一次性去掉自身的所有委託。

註:最終的實現代碼可以在這裡下載:http://download.csdn.net/detail/gouki04/3641328

2.單委託

// 無參的單委託實現
class CDelegate
{
public:
typedef CDelegate IDelegate;
CDelegate () : mDelegate(0) { }
CDelegate (const CDelegate& _event)
{
// 在拷貝構造時,將被拷貝的委託去掉,即委託只存在一份
mDelegate = _event.mDelegate;
const_cast<CDelegate&>(_event).mDelegate = 0;
}
~CDelegate () { clear(); }
bool empty() const { return mDelegate == 0; }
void clear()
{
if (mDelegate)
{
delete mDelegate;
mDelegate = 0;
}
}
CDelegate & operator=(IDelegate* _delegate)
{
delete mDelegate;
mDelegate = _delegate;
return *this;
}
CDelegate & operator=(const CDelegate& _event)
{
// 在賦值時,將右值的委託去掉,即委託只存在一份
delete mDelegate;
mDelegate = _event.mDelegate;
const_cast<CDelegate&>(_event).mDelegate = 0;
return *this;
}
void operator()( )
{
if (mDelegate == 0) return;
mDelegate->invoke( );
}
private:
IDelegate * mDelegate;
};

    可以看到,單委託只實現了 = 運算子,沒有實現 += 運算子。而且在賦值時會將原委託去掉,確保只有一份委託。其實單委託跟普通函數指標差不多,在使用單委託的地方可以換成使用普通函數指標。

3.斷開委託

// 斷開委託的基類
class IDelegateUnlink
{
public:
virtual ~IDelegateUnlink() { }

IDelegateUnlink() { m_baseDelegateUnlink = this; }
bool compare(IDelegateUnlink * _unlink) const { return m_baseDelegateUnlink == _unlink->m_baseDelegateUnlink; }

private:
IDelegateUnlink * m_baseDelegateUnlink;
};

    所謂斷開委託,只能用在多重委託,即CMultiDelegate中,可以斷開自身與其相連的所有委託。使用方法就在將自身的類從IDelegateUnlink派生,然後使用CMultiDelegate中的clear函數即可斷開委託,在下面會有例子說明。

4.測試

/* 測試Delegate對不同函數的支援,可以參考下不同函數的使用方式 */
#include "delegate.h"
#include <iostream>

using namespace std;

// 普通函數1
void func(int a, int b)
{
cout << "func(" << a << ", " << b << ")" << endl;
}

// 普通函數2
void func2(int a, int b)
{
cout << "func2(" << a << ", " << b << ")" << endl;
}

// 普通類
class NormalClass
{
public:
// 類的普通成員函數
void normalFunc(int a, int b)
{
cout << "NormalClass::normalFunc(" << a << ", " << b << ")" << endl;
}
};

// 實現了IDelegateUnlink的類
class BaseUnlinkClass : public delegates::IDelegateUnlink
{
public:
// 類的虛函數
virtual void virFunc(int a, int b)
{
cout << "BaseUnlinkClass::virFunc(" << a << ", " << b << ")" << endl;
}

// 類的普通成員函數
void normalFunc(int a, int b)
{
cout << "BaseUnlinkClass::normalFunc(" << a << ", " << b << ")" << endl;
}
};

class DerivedClass : public BaseUnlinkClass
{
public:
// 類的虛函數
virtual void virFunc(int a, int b)
{
cout << "DerivedClass::virFunc(" << a << ", " << b << ")" << endl;
}

// 類的靜態成員函數
static void staticFunc(int a, int b)
{
cout << "DerivedClass::staticFunc(" << a << ", " << b << ")" << endl;
}
};

// 模板函數
template<class T>
void TFunc(T a, T b)
{
cout << "TFunc(" << a << ", " << b << ")" << endl;
}

int main()
{
BaseUnlinkClass *baseUnlinkClass = new BaseUnlinkClass;
DerivedClass *derivedClass = new DerivedClass;
NormalClass *normalClass = new NormalClass;

// 定義委託
typedef delegates::CMultiDelegate2<int, int> EvenetHandler;
EvenetHandler event;

// 添加普通函數
event += newDelegate(func);
event += newDelegate(func2);

// 添加類的普通成員函數
event += newDelegate(normalClass, &NormalClass::normalFunc);
event += newDelegate(baseUnlinkClass, &BaseUnlinkClass::normalFunc);

// 添加類的虛函數
event += newDelegate(baseUnlinkClass, &BaseUnlinkClass::virFunc);
event += newDelegate(derivedClass, &DerivedClass::virFunc);
// 注意在多態下,使用基類指標時,函數指標要用基類的函數指標,不能用衍生類別的
// 但是在調用時會響應多態,也就是會調用衍生類別的虛函數
event += newDelegate((BaseUnlinkClass*)derivedClass, &BaseUnlinkClass::virFunc);

// 添加類的靜態成員函數
event += newDelegate(&DerivedClass::staticFunc);

// 添加模板函數
event += newDelegate(TFunc<int>);

// 觸發事件
event(1, 2);
cout << endl;

// 去掉函數
event -= newDelegate(func);

// 去掉baseUnlinkClass所有的函數
event.clear(baseUnlinkClass);

// 去掉derivedClass所有的函數
// 注意靜態成員函數staticFunc不會去掉
event.clear(derivedClass);

//event.clear(normalClass);
// 錯誤調用,normalClass不是IDelegateUnlink的衍生類別
// 不能使用clear去掉自身的函數
// 應該使用如下方法
event -= newDelegate(normalClass, &NormalClass::normalFunc);

// 觸發事件
event(2, 3);
cout << endl;

return 0;
}

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.