2014年5月22日 星期四

delegate 2.2 元件

相較於先前的版本,改用 operator=()/operator+=() 取代 Bind() 的功能,operator-=() 取代 Unbind 的功能;成員函數不再能直接設定,而是先用 class bind 包裝之後再設定給 delegate。簡介如下:

  • 須搭配 CxxlMan 程式庫
  • 可代理一般函數指標或成員函數指標(須先用 bind 包裝),參數最多 10 個
  • 對於有回傳值的的格式,只能設定一筆函數指標資料,多次設定後 者會取代前者,若未設定函數指標資料,執行叫用將會 throw DelegateErr_NoBind
  • 對於無回傳值的的格式,可以設定多筆函數指標資料,且會傳回一個 DelegateID,此  ID 可刪除用
  • 設定的方式採用運算元 operator=()(用於取代,即原有的全刪除),或  operator+=()(用於增加)
  • 刪除的方式採用運算元 operator-=(ID)(只刪一個),或用 Clear() 全刪除

下載點:
https://www.dropbox.com/s/b1zht5aid8hrakc/delegate%202.2.7z
http://pan.baidu.com/s/1jG1bqCm




以下是簡單的使用範例,這範例是把 delegate 當 event handler 來使用:

#include <iostream>
#include <C:\delegate 2.2\DELEGATE.HPP>

using namespace std;
using namespace CxxlMan;

// 這計算器只提供除法功能
class calculator
{
  int m_dividend;

  void DoDivisorIsZero()
  {
    OnDivisorIsZero();
  }

  void DoResult(int v)
  {
    OnResult(v);
  }

  void DoWork()
  {
    try
    {
      int v = OnGetDivisor();
      *this / v;
    }
    catch(DelegateErr_NoBind Err)
    {
      cout << "OnGetDivisor 未設定" << endl;
    }
  }

public:
  // Constructor
  calculator(int dividend) // 建構時就得提供被除數
  {
    m_dividend = dividend;
  }

  // Destructor
  ~calculator()
  {
  }

  // 除法運算元
  void operator/(int divisor)
  {
    if(divisor == 0)
      DoDivisorIsZero();
    else
    {
      int r = m_dividend / divisor;
      DoResult(r);
    }
  }

  // 會要求提供一個除數
  void Work()
  {
    DoWork();
  }

  delegate<int()> OnGetDivisor; // Work() 執行時,要求提供一個除數的事件
  delegate<void()> OnDivisorIsZero; // 告知計算結果的事件
  delegate<void(int)> OnResult; // 除數為 0 時的事件
};

// 用一般函數作為事件的處理函數
void ShowResultEvent(int v)
{
  cout << "Result is: " << v << endl;
}

// 提供成員函數作為事件的處理函數
class ShowGirl:public cxxlObject
{
public:
  ShowGirl()
   :cxxlObject(Spirit_Easy)
  {}

  ~ShowGirl(){}


  // 用成員函數作為事件的處理函數
  void DivisorIsZeroEvent()
  {
    cout << "ShowGirl: Divisor Is Zero!" << endl;
  }

  // 用成員函數作為事件的處理函數
  void ResultEvent(int v)
  {
    cout << "ShowGirl: the Result is " << v << endl;
  }

  int GetDivisorEvent()
  {
    int v;
    cout << "Divisor: ";
    cin >> v;
    return v;
  }

};

int main()
{
  calculator Cal(100);

  // 一般函數直接設定就可以了
  Cal.OnResult = ShowResultEvent;

  Smart_Ptr<ShowGirl> ShowGirl_Ptr = new ShowGirl;

  // 這兩個都是用取代的方法來設定事件處理函數,先前 ShowResultEvent 會被取代
  // 且須先用 bind 來包裝物件及其成員函數,才能設定
  Cal.OnDivisorIsZero = bind<ShowGirl>(ShowGirl_Ptr, &ShowGirl::DivisorIsZeroEvent);
  Cal.OnResult = bind<ShowGirl>(ShowGirl_Ptr, &ShowGirl::ResultEvent);

  cout << "Cal / 10;" << endl;
  Cal / 10;
  cout << "--------------------------------------" << endl;

  // 增設事件處理函數,原先的事件處理函數依然存在
  Cal.OnResult += ShowResultEvent;
  cout << "Cal / 20;" << endl;
  Cal / 20;

  cout << "--------------------------------------" << endl;

  cout << "Cal / 0;" << endl;
  Cal / 0;

  cout << "--------------------------------------" << endl;

  cout << "Cal.Work();" << endl;
  Cal.Work();

  cout << "--------------------------------------" << endl;

  Cal.OnGetDivisor = bind<ShowGirl>(ShowGirl_Ptr, &ShowGirl::GetDivisorEvent);
  cout << "Cal.Work();" << endl;
  Cal.Work();

  return 0;
}




沒有留言:

張貼留言