1.引言
按上一篇文章的方法,你已經可以使用任意參數的函數委托了。這裡介紹下MyGUI實現的兩個輔助類,CDelegate類和IDelegateUnlink。如果你不為了深入了解MyGUI的委托實現,可以跳過此處。CDelegate即為單委托,實際效果跟函數指針差不多,於CMultiDelegate的區別在於其不支持多播。而IDelegateUnlink類主要是在CMultiDelegate中使用,在多播下一次性去掉自身的所有委托。
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()
{ www.2cto.com
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;
};
// 無參的單委托實現
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;
};
// 斷開委托的基類
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;
}
/* 測試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;
}
摘自:gouki04的專欄