2012-10-05 22 views
4

大家好:我是一個經驗豐富的C#程序員試圖做的在C++的一些工作,我不知道這樣做的正確方法:C#程序員嘗試在C++事件

我創作一需要通知消費類的事情發生了。

如果我在c#中寫這個,我會在我的類上定義一個事件。

在C++中沒有事件,所以我想弄清楚什麼是正確的方法來做到這一點。我曾考慮過回調函數,但是如何處理我想執行成員函數(而不是靜態函數)的情況。

更具體地說,我真正需要做的是處理事件,但可以在處理事件的對象實例中訪問成員狀態。

我一直在尋找std :: tr1:函數,但我無法正常工作。

我不假設任何人都想將以下示例c#示例轉換爲正確/最佳實踐C++(我需要ANSI C++)的示例? (請記住,我幾乎沒有C++的經驗 - 不要以爲我知道任何早已建立的C++約定 - 我不知道);

一個簡單的C#控制檯應用程序(我的機器上工作):

 

using System; 

namespace ConsoleApplication1 
{ 
    public class EventSource 
    { 
     public event EventHandler<EchoEventArgs> EchoEvent; 

     public void RaiseEvent(int echoId) 
     { 
      var echoEvent = this.EchoEvent; 
      if (echoEvent != null) 
       echoEvent(this, new EchoEventArgs() {EchoId = echoId}); 
     } 
    } 

    public class EchoEventArgs : EventArgs 
    { 
     public int EchoId { get; set; } 
    } 

    public class EventConsumer 
    { 
     public int Id { get; set; } 
     public EventConsumer(EventSource source) 
     { 
      source.EchoEvent += OnEcho; 
     } 

     private void OnEcho(object sender, EchoEventArgs args) 
     { 
      // handle the echo, and use this.Id to prove that the correct instance data is present. 
      Console.WriteLine("Echo! My Id: {0} Echo Id: {1}", this.Id, args.EchoId); 
     } 
    } 

    internal class Program 
    { 
     private static void Main(string[] args) 
     { 
      var source = new EventSource(); 
      var consumer1 = new EventConsumer(source) { Id = 1 }; 
      var consumer2 = new EventConsumer(source) { Id = 2 }; 
      source.RaiseEvent(1); 
      Console.ReadLine(); 
     } 
    } 
} 
 
+4

[升壓信號](http://www.boost.org/doc/libs/1_51_0/doc/html/signals.html)。 –

+0

@JerryCoffin:提升信號ANSI嗎? (這個代碼必須在Windows和Unix上編譯)。另外,你能告訴我一個例子嗎? – JMarsch

+1

是的,Boost信號中的代碼非常便攜。我鏈接到的頁面包括[文檔/視圖示例](http://www.boost.org/doc/libs/1_51_0/doc/html/signals/tutorial.html#id3195532)。 –

回答

3

其基本思想是將函數對象,例如std::function<Signature>等作爲回調函數。這些不是函數指針,但可以調用。標準C++庫(用於C++ 2011)包含許多類和函數,例如std::mem_fn()std::bind(),它們允許使用包括成員函數在內的函數作爲函數對象。

缺少的部分是支持多個事件的東西被註冊:std::function<Signature>代表一個功能。但是,很容易將它們放入std::vector<std::function<Signature>>。什麼變得更有趣(並且要求可變參數模板容易完成)是創建一個事件類,它封裝了多個事件的抽象,開始註冊,可能未註冊,並被調用。

+1

...並且如果你不能使用C++ 11(這會很可惜),[boost](http://www.boost.org/doc/libs/1_51_0)也可以爲你提供所有這些東西。 – vines

+0

@Dietmar我很難讓bind()與我的實例成員一起工作。你能展示一個代碼示例嗎? – JMarsch

+1

@JMarsch:現在我無法測試它,但它看起來像這樣:'std :: bind(&Class :: member,&obj,_1,_2)'用於綁定成員函數以產生兩個參數函數。如果成員函數被重載,則不幸的是需要將成員指針轉換爲正確的成員指針類型以選擇正確的指針。 –

1

C++有仿函數的概念:一個可調用對象。你需要閱讀有關它們。請參考operator()。你傳遞這樣一個對象的一個​​實例。之後,您可以將其稱爲常規功能。它可以保持一個狀態。

+0

什麼可以collable對象做與事件上升和處理? – 2012-10-05 22:35:52

+0

@Desolator你使用它們來實現事件和處理程序。基里爾可能會對此更加明確。 – wjl

+0

@wjl,你說得對。我只談到了部分問題。只有'我想執行一個成員函數'.. –

1

Boost中還有Signals2庫,它提供了一個非常接近實際C#事件的API,至少在慣用意義上。

1

Qt擁有的東西,可以幫助你所謂的信號和槽:http://qt-project.org/doc/qt-4.8/signalsandslots.html

它允許您指定哪些信號(要聽的事件)和一個對象具有插槽(接收方)然後你可以連接它們。不止一個對象可以聽你提到你需要的信號。

Qt是一個很大的應用程序框架,所以我不確定如何只使用信號插槽的一部分。但如果你正在構建一個完整的GUI應用程序,其餘的Qt可能也會使你受益(很多UI事件都是基於信號和插槽)。