青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

posts - 1,  comments - 6,  trackbacks - 0

??? 在 Java C #等語言或者說其類庫中,都實現了事件模型。而 c++ 語言本身并沒有定義事件機制,并且在目前眾多優秀的 c++ 類庫,包括 STL Boost 等都沒有實現類似的事件機制。當我們被 MFC 的消息搞得頭昏眼花之時,是否有沖動自己去實現一個簡單的事件模型呢。我想,有著相同想法的人肯定很多,而真正動手來寫可能會碰到各種各樣的困難。下面就讓我們一步步來編寫一個簡單的事件模型。

?

一、 了解事件模型的機制

在開始之前,我們有必要簡單的了解一下事件模型的機制。事實上,事件模型的機制不止一種, Java c# 的事件機制就不太一樣,不過事件模型的基礎都是一樣,那就是一般都使用 Observer 設計模式。關于 Observer 設計模式,希望詳細了解的朋友可以參考《設計模式》一書,在這里我們就不詳細的介紹,只是參照 c# 的事件機制來實現。

c# 中,我們可以以 event 關鍵字聲明一個事件,然后我們可以將一個函數委托掛接在這個事件上,當事件被調用時,則所有掛接的函數也會被調用。這里有一個比較難以理解的詞大概是委托,其實也不難理解。委托其實就是一種函數包裝類,這種類可以把任何函數的指針保存起來,等到需要調用的時候再調用,并且這種類的實例必須能夠掛接到事件之中。

看了上面這段話,是不是覺得其實事件模型也并不復雜。還想對事件模型了解得更多?我這里就不繼續了,感興趣的朋友可以查找一下相關的資料。下面我們就開始在 c++ 中編寫一個簡單的事件模型。

?

二、 設計一個簡單的 c++ 事件模型

因為一個事件模型其實就是一個典型的 Observer 設計模式,因此最重要的就是 Subject( 目標類 ) Observer( 觀察者類 ) 的設計。

首先,我們需要一個事件類,它其實是一個抽象的 Subject 。它是一個基類,所有的其他事件都從它繼承,并且用戶只需要從這個基類繼承就可以自定義事件。我們不仿將這個類定義為 CEvent CEvent 的聲明如下:

class CEvent ?

{

public :

????????

???????? typedef list < CEventHandler > data_type ;

?

???????? CEvent ();

?

???????? virtual ~ CEvent ();

?

???????? void operator ()()

???????? {

???????? ???????? data_type :: iterator it ;

??????????????????????????? ????????

?????????????????? for ( it = m_observer . begin (); it != m_observer . end (); ++ it )

?????????????????? {

?????????????????? ???????? (* it )(* this );

?????????????????? }

???????? }

?

???????? CEvent & operator += ( const CEventHandler & handler )

???????? {

???????? ???????? Register ( handler );

?????????????????? return * this ;

???????? }

?

???????? CEvent & operator -= ( const CEventHandler & handler )

???????? {

???????? ???????? UnRegister ( handler );

?????????????????? return * this ;

???????? }

?

???????? void Register ( const CEventHandler & handler )

???????? {

???????? ???????? m_observer . push_back ( handler );

???????? }

?

???????? void UnRegister ( const CEventHandler & handler )

???????? {

???????? ???????? m_observer . remove ( handler );

???????? }

?

protected :

?

???????? // 將偵聽的所有函數或者仿函數的集合起來

???????? data_type m_observer ;

};

?

其次,這個事件可以掛接任意的函數,也就是它可以保存所有的掛接函數。在 c++ 中,我們大致有三種類型的函數,全局或者靜態函數、成員函數、仿函數。要在 CEvent 中實現一個或者多個方法來執行掛接的任務不太現實。我們參考 c# 的實現方法,可以先實現一個委托類,將各種函數保存起來。然后再使用 CEvent 對這個委托類進行掛接。我們不仿稱這個類為 CEventHandler

然后,我們的這個委托類需要能夠保存所有的函數。在 c++ 里,我們能夠很容易的得到函數的指針,只需要在函數名前加 & ,但是各種函數,特別是成員函數它是沒有類型的,這就要有一種機制,將所有的函數轉換為同一種類型。因為函數是沒有類型,也相當于每一個函數都是一種類型,解決這個問題的方法其實就是使用模板類。因此,我們先定義一個虛基類 CFunImpl 。對三種不同的函數,我們分別從 CfunImpl 繼承三種不同的子類, CstaticFun CmemFun,CFunctor CstaticFun 表示全局的或者靜態的函數,不過這必須是一個模板類,對于每一個靜態或者全局函數,都是模板類的一個特化。類聲明的代碼如下:

template < typename Fun >

???????? class CStaticFun : public CFunImpl

???????? {

???????? public :

?

???????? ???????? CStaticFun ( const Fun & fun ) : m_fun ( fun ){};

??????????????????

?????????????????? virtual ~ CStaticFun ()

?????????????????? {

?????????????????? }

???????? protected :

?????????????????? Fun m_fun ;

???????? };

?

對于 CmemFun 類,我們如法炮制,不過我們這時需要保存兩個成員變量,一個是成員函數的指針,另一個則是該成員函數所屬的對象的指針。類聲明的代碼如下:

?

template < typename PointerToObj , typename PointerToMemFun >

???????? class CMemFun : public CFunImpl

???????? {

???????? public :

?

???????? ???????? CMemFun ( const PointerToObj & pObj , PointerToMemFun pMemFn )

??????????????????????????? : m_pObj ( pObj ), m_pMemFun ( pMemFn )

?????????????????? {

?????????????????? }

?

virtual ~ CMemFun ()

?????????????????? {

?????????????????? }

??????????????????

???????? protected :

???????? ???????? PointerToObj m_pObj ;

???????? ???????? PointerToMemFun m_pMemFun ;

};

?

對于仿函數,我們這里先不講,因為仿函數使用得很少,并且這還涉及到仿函數的概念,有興趣的朋友可以在閱讀完本文之后自己來實現。

好,到現在為止,我們可以將所有的函數使用 CfunImpl 來表示了。因此,我們可以在委托類 CEventHandler 中保存 CfunImpl* 來達到我們的目的。 CEventHandler 的聲明如下:

???????? class CEventHandler ?

???????? {

???????? public :

?????????????????? virtual ~ CEventHandler ()

?????????????????? {

?????????????????? ???????? Clear ();

?????????????????? }

?

???????? ???????? template < class Fun >

???????? ???????? CEventHandler ( const Fun & fun )

??????????????????????????? : m_pImpl ( new CStaticFun < Fun >( fun ))

?????????????????? {}

??????????????????

???????? ???????? CEventHandler ( const CEventHandler & fun )

??????????????????????????? : m_pImpl ( NULL )

?????????????????? {

?????????????????? ???????? * this = fun ;

?????????????????? }

?

?????????????????? void Clear ()

?????????????????? {

??????????????????????????? if ( m_pImpl )

??????????????????????????? {

??????????????????????????? ???????? delete m_pImpl ;

??????????????????????????? ???????? m_pImpl = NULL ;

??????????????????????????? }

?????????????????? }

?

???????? ???????? CEventHandler & operator = ( const CEventHandler & fun )

?????????????????? {

?????????????????? ???????? Clear ();

?

??????????????????????????? if ( fun . m_pImpl )

??????????????????????????? {

??????????????????????????? ???????? m_pImpl = fun . m_pImpl -> Clone ();

??????????????????????????? }

?

?????????????????? ???????? return * this ;

?????????????????? }

??????????????????

?????????????????? // 成員函數

???????? ???????? template < typename PointerToObj , typename PointerToMemFun >

?????????????????? ???????? CEventHandler ( const PointerToObj & pObj , const PointerToMemFun & pMemFun )

??????????????????????????? : m_pImpl ( new CMemFun < PointerToObj , PointerToMemFun >( pObj , pMemFun ))

?????????????????? {}

?

?????????????????? void operator ()( CEvent & e )

?????????????????? {

if ( m_pImpl )

??????????????????????????? {

??????????????????????????? ???????? (* m_pImpl )( e );

}

?????????????????? }

?

?????????????????? bool operator == ( const CEventHandler & handler )

?????????????????? {

??????????????????????????? if ( m_pImpl == NULL || handler . m_pImpl == NULL )

??????????????????????????? {

??????????????????????????? ???????? return true ;

??????????????????????????? }

?

??????????????????????????? if ( typeid ( m_pImpl ) == typeid ( handler . m_pImpl ))

??????????????????????????? {

??????????????????????????? ???????? return (* m_pImpl ) == (*( handler . m_pImpl ));

??????????????????????????? }

?

?????????????????? ???????? return false ;

?????????????????? }

?

???????? protected :

???????? ???????? CFunImpl * m_pImpl ;

?

???????? };

?

不過要實現事件機制,我們還需要 CfunImpl* 的子類必須實現幾個方法。

第一個方法就是調用函數的方法,我們這里要求重載 void operator()(CEvent& e); 來達到目的。

第二個方法就是 operator== ,為什么需要這個方法呢。因為對于 CEvent 來說,調用 UnRegister() 時,我們必須找到我們使用 Register() 添加到 list 中的函數,這時我們需要判斷兩個 CEventHandler 對象是否相等,這是件麻煩事情。 CEventHandler 保存的是 CFunImpl 的指針,好吧,這個我們就要求 CfunImpl 的子類必須實現重載 operator==

第三個方法,從 CfunImpl 繼承必須實現 Clone() 方法。 Clone() 方法可以讓 CEventHandler 實現拷貝。具體的實現方法我們可以查看源碼。

?

三、 使用事件模型

一個簡單的事件模型基本完成了。現在我們可以編寫一個例子來演示一下如何來使用這個事件模型。其實使用起來很簡單。

我們可以聲明一個 CEvent 或者 CEvent 子類的實例。讓需要監聽的函數掛接到這個 CEvent 中,我們實現了 Register() 函數和 += 操作符,都可以使用。掛接的語句就像這樣:

CEvent evt;

CobserverTest obj;

evt += CEventHandler (& obj , &( CObserverTest :: OnStartEvent ));

當事件的 operator() 方法調用時,就會自動調用我們的監聽函數。具體的例子可以查看提供的源代碼。

?

四、 模型的缺陷和改進

到現在為止,我們終于實現了一個簡單的事件模型。它可以有效的工作,并且與平臺無關。當然,要求你的編譯器盡量的支持 c++ 標準。如果你的編譯器對 c++98 標準支持不夠,也許它不能夠工作正常。筆者在 VC6SP6 VC2005 中測試均通過。

不過這個模型還有可以改進的余地。其一、目前只是支持同步操作,即當你的事件進行調用時是在同一線程里順序進行。要改進到支持異步調用就必須在每次調用時在一個新的線程中進行調用。因此我們需要一個線程機制來完成這個工作。如果在一個特定的平臺中使用,如 VC 中,我們可以在響應函數中創建一個新的線程。

其二、目前的所有的函數參數必須為 (CEvent& e) ,不能寫成 (CchildEvent& e) 。要對這個限制進行改進,就需要編譯器支持虛模板成員函數的機制。不過在 VC6 VC2005 中,均不支持這種特性。因此要么尋求它法,要么就等到編譯器的支持吧。

其三、線程安全,這個簡單的事件模型使用到了 STL 中的 list 組件,但是并非所有的 list 實現都是線程安全的。建議大家采用 stlport ,因為它的實現是線程安全的,如果沒有采用線程安全的實現,那么在調用 Register UnRegister 時最好能夠實現互斥。

?

限于筆者知識水平和文筆有限,不當之處肯定很多。若你有好的想法和建議,可以 email 告訴我。本文中所涉及到的所有源碼可以從這里下載http://m.shnenglu.com/Files/lunny/CEventModel.rar

?

????????????? ???????????????????? ???????????????????? ?????? ????????????? ???????????????????? ????????????? 肖倫文

xiaolunwen@hotmail.com
posted on 2006-07-30 20:48 風間蒼月 閱讀(4315) 評論(6)  編輯 收藏 引用
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美日韩国产丝袜另类| 亚洲人屁股眼子交8| 久久精品国产久精国产思思| 欧美精品一区在线观看| 久久精品青青大伊人av| 国产一区二区三区四区在线观看 | 久久精品视频网| 亚洲国产综合91精品麻豆| 久久动漫亚洲| 亚洲精品一区二区三区99| 99精品国产在热久久下载| 狠狠88综合久久久久综合网| 亚洲欧美日韩精品久久奇米色影视| 正在播放亚洲| 亚洲人成7777| 欧美日本韩国一区| 欧美三级乱码| 欧美 日韩 国产精品免费观看| 亚洲一区欧美一区| 欧美成人精品在线观看| 亚洲人成亚洲人成在线观看图片| 欧美韩日一区二区| 亚洲天天影视| 亚洲日韩成人| 久久九九免费视频| 亚洲欧美变态国产另类| 在线观看一区二区视频| 欧美国产精品v| 欧美日韩精品久久| 老司机精品久久| 国产精品第十页| 欧美午夜在线视频| 欧美精品在线观看| 欧美女同视频| 欧美性生交xxxxx久久久| 欧美猛交免费看| 欧美高清在线一区| 久久狠狠一本精品综合网| 久久另类ts人妖一区二区| 欧美aⅴ99久久黑人专区| 玖玖精品视频| 国产精品欧美久久| 亚洲视频碰碰| 午夜在线a亚洲v天堂网2018| 亚洲午夜精品久久| 一二三区精品福利视频| 久久视频免费观看| 国产精品免费电影| 精品999网站| 亚洲一区二区网站| 亚洲在线视频网站| 裸体丰满少妇做受久久99精品| 黑人极品videos精品欧美裸| 国产字幕视频一区二区| 欧美亚洲日本网站| 亚洲国产三级在线| 一本一道久久综合狠狠老精东影业 | 国产一区二区按摩在线观看| 国内自拍一区| 一本色道久久综合亚洲精品不| 亚洲精品一区二区三区av| 欧美专区在线观看一区| 亚洲电影在线看| 亚洲无亚洲人成网站77777| 欧美xx69| 性亚洲最疯狂xxxx高清| 久久久www成人免费无遮挡大片| 99国产精品久久久久久久| 免费国产自线拍一欧美视频| 日韩午夜av电影| 欧美一区二区三区在| 在线观看一区| 亚洲成在线观看| 久久人人97超碰精品888| 欧美大色视频| 亚洲欧洲视频在线| 欧美中文字幕久久| 国产精品欧美激情| 久久久久久久网站| 久久日韩精品| 亚洲性线免费观看视频成熟| 亚洲第一视频网站| 国产精品美女久久久久av超清 | 一区二区三区欧美在线| 国产精品第一页第二页第三页| 亚洲精品久久久久久下一站 | 亚洲精品一区二区三区婷婷月| 久久久久久成人| 欧美一级成年大片在线观看| 国产日韩一区欧美| 亚洲欧美日韩人成在线播放| 欧美日韩和欧美的一区二区| 亚洲精品乱码久久久久久蜜桃麻豆 | 久久躁狠狠躁夜夜爽| 国产亚洲a∨片在线观看| 久久先锋资源| 亚洲日本aⅴ片在线观看香蕉| 亚洲欧美韩国| 在线视频免费在线观看一区二区| 亚洲一区综合| 久久久精品国产99久久精品芒果| 免费看成人av| 亚洲国产精品一区二区www在线 | 乱人伦精品视频在线观看| 国产一区二区三区四区三区四| 欧美www视频| 亚洲性图久久| 国产精品久久网站| 亚洲欧美中文字幕| 亚洲一区二区三区在线观看视频| 欧美91精品| 欧美激情精品久久久久久蜜臀| 亚洲人成网在线播放| 免费成人网www| 一区二区免费在线视频| 香蕉久久夜色| 亚洲免费不卡| 欧美四级在线| 亚洲精品小视频在线观看| 国产欧美精品一区二区色综合| 一区二区三区高清不卡| 亚洲女爱视频在线| 在线播放国产一区中文字幕剧情欧美| 欧美日韩国产首页在线观看| 欧美亚洲一区二区三区| 欧美电影免费| 午夜在线一区| 亚欧成人精品| 亚洲欧美在线磁力| 免费高清在线一区| 久久精品视频va| 性做久久久久久久免费看| 日韩一区二区久久| 亚洲视频电影图片偷拍一区| 欧美电影免费观看高清| 午夜在线精品偷拍| 午夜精品福利一区二区三区av | 亚洲午夜免费福利视频| 欧美色精品在线视频| 欧美日韩在线免费| 麻豆视频一区二区| 欧美怡红院视频一区二区三区| 亚洲精品国产精品国自产观看| 久久亚洲精品一区二区| 亚洲一区二区精品| 亚洲自拍偷拍麻豆| 亚洲精品视频啊美女在线直播| 好看不卡的中文字幕| 在线国产欧美| 亚洲三级色网| 91久久国产综合久久| 一本色道久久综合亚洲精品高清| 久久精品欧美日韩精品| 亚洲深夜福利视频| 欧美一级播放| 久久久久久一区二区| 欧美中文字幕精品| 亚洲在线视频网站| 久久精品免费电影| 亚洲区欧美区| 亚洲欧美日本精品| 裸体丰满少妇做受久久99精品 | 亚洲视频综合在线| 亚洲男人av电影| 亚洲人成小说网站色在线| 欧美一区二区三区视频| 亚洲视频在线观看三级| 亚洲电影免费观看高清完整版在线观看 | 亚洲第一主播视频| 亚洲精品日韩在线| 久久一区视频| 亚洲一线二线三线久久久| 亚洲福利视频三区| 欧美福利网址| 亚洲日本中文字幕区| 免费看黄裸体一级大秀欧美| 夜夜精品视频| 欧美日韩一区在线播放| 在线播放不卡| 久久久噜噜噜久久| 性欧美暴力猛交69hd| 国产专区欧美专区| 免费在线一区二区| 欧美人与禽猛交乱配| 亚洲一区二区三区在线| 亚洲国产婷婷综合在线精品| 欧美精品v日韩精品v韩国精品v| 亚洲日本欧美天堂| 亚洲全黄一级网站| 欧美精品一区二区三区在线播放 | 日韩亚洲欧美在线观看| 女人色偷偷aa久久天堂| 亚洲图片激情小说| 国产精品一区久久久久| 久久久久se| 欧美精品三级| 久久这里只有| 欧美日韩中文字幕精品| 亚洲在线观看视频| 久久电影一区|