【已解決】C++ Event 的實作方式

Event 在 Windows 的程式設計中,已經習以為常,尤其是 Windows 的 Event。但要在 C++ 中實作,還真不曉得要如何下手,原本在 C# 中如此基本的東西,轉到 C++ 竟是如此困難。

還好 Microsoft 還是留了一手 Event Handling,但看了半天還不是很懂,於是從 Sample code 中實驗終於大致瞭解了,所以記錄以備後用 (雖然 Microsoft 說這個功能要取消了,不過取消前還是將就著用吧!)


#include "stdafx.h"
#include <iostream>

using namespace std;

[event_source(native)]
struct IAnimal {
 virtual void Move() = 0;
 __event void OnMoved(int number);
};

class Dog : public IAnimal {
public:
 void Move() { cout << "Dog is moving." << endl; __raise OnMoved(5); }
};

class Cat : public IAnimal {
public:
 void Move() { cout << "Cat is moving." << endl; __raise OnMoved(7); }
};

[event_receiver(native)]
class Home {
public:
 void OnMoved(int number) { cout << "It has moved " << number << " steps at home." << endl; }
};

[event_receiver(native)]
class Office {
public:
 void OnMoved(int number) { cout << "It has moved " << number << " steps at office." << endl; }
};

int _tmain(int argc, _TCHAR* argv[])
{
 Dog dog;
 Cat cat;
 Home home;
 Office office;

 __hook(&Dog::OnMoved, &dog, &Home::OnMoved, &home);
 __hook(&Cat::OnMoved, &cat, &Office::OnMoved, &office);

 dog.Move();
 cat.Move();

 __unhook(&Dog::OnMoved, &dog, &Home::OnMoved, &home);
 __unhook(&Cat::OnMoved, &cat, &Office::OnMoved, &office);

 return 0;
}

  1. 觸發 Event 的 class 為發送端,必須在 class 宣告前面加上 [event_source(native)] 的屬性,並在 Event  函式簽章前面加上 __event。因目前在實作介面,所以就把 Event 宣告在上層的介面中,則實作該介面的 class 即繼承該 Event。
  2. class 中的 Method 要觸發 Event,只要在 Event 函式前面加上 __raise 呼叫即可。
  3. Event Handler 的 class 為接收端,必須在 class 宣告前面加上 [event_receiver(native)] 的屬性。
  4. 要連接 Event 與 Event Handler 必須使用 __hook,若在接收端  class 的 Method 中使用,則可以省略第 4 個參數 (預設值為 this)。而第 1 個參數也可以直接用介面 IAnimal::OnMoved,這樣方便實作該介面的 class  設定。
  5. 同一個 Event 可以串接多個 Event Handler,但最後 hook 的 Handler 會最先執行,如果有順序要求的話要特別注意。
  6. 若不使用該 EventHandler 則要呼叫 __unhook 移除,若該 Event 串接多個 Event Handler,則可以隨時移除其中任何一個,並沒有順序關係。
最後程式的執行結果如下

Dog is moving.
It has moved 5 steps at home.
Cat is moving.
It has moved 7 steps at office.

PS : Event Handler 使用完畢後必須執行 unhook 的動作,否則會產生 Memory Leaks



其實用觀察者模式就可以輕易地實作 Event 的功能了!!!

留言

這個網誌中的熱門文章

Linux 批次檔的寫法

【分享】如何顯示 Debug Message

[分享] Visual Studio 遠端偵錯