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

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

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()
    {
        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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章