9.9.7 委托和事件(5)
Door类还有一个触发两次Knock事件的公有函数TriggerEvent(),两次触发使用不同的实参。这两个实参将被传递给已注册的接收Knock事件通知的函数。我们看到,触发事件实质上与调用委托相同。
我们可以像下面这样定义一个能够处理Knock事件的类:
- public ref class AnswerDoor
- {
- public:
- void ImIn(String^ name)
- {
- Console::WriteLine(L"Come in {0}, it's open.",name);
- }
-
- void ImOut(String^ name)
- {
- Console::WriteLine(L"Go away {0}, I'm out.",name);
- }
- };
AnswerDoor类有两个能够处理Knock事件的公有函数成员,因为二者的形参列表和返回类型与DoorHandler委托的声明所指定的一致。
在能够注册将接收Knock事件通知的函数之前,我们需要创建一个Door对象。创建Door对象的方法如下:
- Door^ door = gcnew Door;
现在,我们可以像下面这样,注册用来接收Door对象中Knock事件通知的函数:
- AnswerDoor^ answer = gcnew AnswerDoor;
- door->Knock += gcnew DoorHandler(answer, &AnswerDoor::ImIn);
第一条语句创建一个AnswerDoor类型的对象,我们需要该对象,因为ImIn()和ImOut()函数不是静态类成员。然后,我们将DoorHandler委托类型的一个实例与door的Knock成员相加。这完全就是给委托添加函数指针的过程,我们可以以相同的方式,添加更多的当Knock事件被触发时将被调用的事件处理函数。我们可以在示例中看一看处理事件的过程。
试一试:处理事件
该示例使用前面的几个类来定义、触发和处理事件:
- // Ex9_19.cpp : main project file.
- // Defining, triggering and handling events.
- #include "stdafx.h"
-
- using namespace System;
-
- public delegate void DoorHandler(String^ str);
-
- // Class with an event member
- public ref class Door
- {
- public:
- // An event that will call functions associated
- // with an DoorHandler delegate object
- event DoorHandler^ Knock;
-
- // Function to trigger events
- void TriggerEvents()
- {
- Knock(L"Fred");
- Knock(L"Jane");
- }
- };
-
- // Class defining handler functions for Knock events
- public ref class AnswerDoor
- {
- public:
- void ImIn(String^ name)
- {
- Console::WriteLine(L"Come in {0}, it's open.",name);
- }
-
- void ImOut(String^ name)
- {
- Console::WriteLine(L"Go away {0}, I'm out.",name);
- }
- };
-
-
- int main(array<System::String ^> ^args)
- {
- Door^ door = gcnew Door;
- AnswerDoor^ answer = gcnew AnswerDoor;
-
- // Add handler for Knock event member of door
- door->Knock += gcnew DoorHandler(answer, &AnswerDoor::ImIn);
-
- door->TriggerEvents(); // Trigger Knock events
- // Change the way a knock is dealt with
- door->Knock -= gcnew DoorHandler(answer, &AnswerDoor::ImIn);
- door->Knock += gcnew DoorHandler(answer, &AnswerDoor::ImOut);
- door->TriggerEvents(); // Trigger Knock events
- return 0;
- }
执行该示例产生下面的输出:
- Come in Fred, it's open.
- Come in Jane, it's open.
- Go away Fred, I'm out.
- Go away Jane, I'm out.
示例说明
我们在main()中首先创建了两个对象:
- Door^ door = gcnew Door;
- AnswerDoor^ answer = gcnew AnswerDoor;
对象door有一个事件成员Knock,对象answer有两个可以处理Knock事件的成员函数。
下一条语句注册answer对象的ImIn()成员,使之接收door对象中Knock事件的通知:
- door->Knock += gcnew DoorHandler(answer, &AnswerDoor::ImIn);
如果有意义,我们还可以注册其他当触发Knock事件时将被调用的函数。
下一条语句调用door对象的TriggerEvents()成员:
- door->TriggerEvents(); // Trigger Knock events
该语句引起两次Knock事件,实参分别是"Fred"和"Jane"。结果是每次事件调用一次ImIn()函数,从而产生前两行输出。
当然,我们可能希望在不同时间根据实际情况,以不同方式对事件作出响应,这正是main()中后面3条语句所演示的事件处理方法:
- door->Knock -= gcnew DoorHandler(answer, &AnswerDoor::ImIn);
- door->Knock += gcnew DoorHandler(answer, &AnswerDoor::ImOut);
- door->TriggerEvents(); // Trigger Knock events
第一条语句从事件中删除指向ImIn()函数的指针,第二条语句注册对象answer的ImOut()函数,使之接收Knock事件通知。当Knock事件被第三条语句触发时,被调用的变为ImOut()函数,因此输出结果就发生了变化。