• <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>
            隨筆 - 55  文章 - 15  trackbacks - 0
            <2012年4月>
            25262728293031
            1234567
            891011121314
            15161718192021
            22232425262728
            293012345

            常用鏈接

            留言簿

            隨筆分類

            隨筆檔案

            搜索

            •  

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            本文章為farproc.com站長(zhǎng)袁曉輝(海洋)的原創(chuàng)文章,作者保留所有權(quán)利。如果轉(zhuǎn)載,請(qǐng)務(wù)必注明來(lái)自www.farproc.com!!

             

            作為一個(gè)C++程序員,學(xué)習(xí)C#應(yīng)該不是一件很困難的事情,因?yàn)?/span>C#的許多特性都是從C++“繼承”(不精確的說(shuō)法)來(lái)的。但是C#作為一門(mén)全新的編程語(yǔ)言,它必然有自己的新特性,而這些C++中并不存在的新特性正是我們從C++轉(zhuǎn)向C#的過(guò)程中必須認(rèn)真重新學(xué)習(xí)的東西。“事件(event)”是C#的一個(gè)比較簡(jiǎn)單的新特性,我們今天就從“事件”開(kāi)始,看一看C#的事件到底是怎么回事。

            C#的事件和Windows窗口編程中提到的“事件”、“消息”、“事件驅(qū)動(dòng)”等在概念上是很類似的。我們?cè)谝粋€(gè)窗口上移動(dòng)鼠標(biāo)指針,系統(tǒng)就會(huì)產(chǎn)生WM_MOUSEMOVE消息(在vb中就是激發(fā)mousemove事件),只要我們告訴系統(tǒng)一個(gè)函數(shù)指針,系統(tǒng)就會(huì)通過(guò)這個(gè)回調(diào)函數(shù)通知我們,這是Windows窗口編程中的“事件”。C#中的事件的外延更廣,任何一個(gè)對(duì)象都可以擁有事件,客戶可以“定制”該對(duì)象的事件,當(dāng)該對(duì)象的內(nèi)部狀態(tài)發(fā)生特定的改變時(shí),就會(huì)通過(guò)定制事件時(shí)指定的函數(shù)代理(delegate)調(diào)用這個(gè)函數(shù)通知客戶。當(dāng)客戶不在需要事件通知時(shí),可以“撤消”對(duì)該事件的定制。

            Now is the show time!模仿秀現(xiàn)在開(kāi)始!

            一、C#

            我們先來(lái)看一個(gè)C#中一個(gè)“事件”的最簡(jiǎn)單例子:

            VS.NET中新建一個(gè)C#Console Application,項(xiàng)目名稱為“eventtest”。為該項(xiàng)目新加一個(gè)類MyClass,對(duì)應(yīng)的源文件為MyClass.cs代碼如下:

            using System;

             

            namespace eventtest

            {

                //定義EventHandler函數(shù)代理

                public delegate void EventHandler();

             

                /// <summary>

                ///

                /// </summary>

                public class MyClass

                {

                    //構(gòu)造函數(shù)

                    public MyClass(){}

                    //聲明一個(gè)事件

                    public event EventHandler AEvent;

                    //激發(fā)事件

                    public void FireEvent()

                    {

                        if(AEvent != null)

                        {

                            //直接把event當(dāng)做函數(shù)調(diào)用

                            AEvent();

                        }

                    }

                }

            }

             

            public event EventHandler AEvent;就是給MyClass定義了一個(gè)事件(通過(guò)event關(guān)鍵字),其事件處理函數(shù)(通知函數(shù))的原型由EventHandler函數(shù)代理(類似C++中的函數(shù)指針)指定。

            FireEvent()成員函數(shù)用于激發(fā)該事件,如果客戶定制了該event,當(dāng)本類對(duì)象的FireEvent()公開(kāi)方法被調(diào)用時(shí),客戶應(yīng)該可以得到通知。在Main函數(shù)里寫(xiě)如下代碼:

            using System;

             

            namespace eventtest

            {

                /// <summary>

                /// Class1 的摘要說(shuō)明。

                /// </summary>

                class Class1

                {

                    /// <summary>

                    /// 應(yīng)用程序的主入口點(diǎn)。

                    /// </summary>

                    [STAThread]

                    static void Main(string[] args)

                    {

                        MyClass Obj = new MyClass();

                        Obj.AEvent += new EventHandler(MyEventHandler);//定制事件

                        Obj.FireEvent();//這行將導(dǎo)致MyEventHandler被調(diào)用

             

                        Obj.AEvent -= new EventHandler(MyEventHandler);//撤消事件

                        Obj.FireEvent();//這里將不會(huì)引發(fā)事件

                       

                        Console.WriteLine("結(jié)束!");

                        Console.ReadLine();

                    }

                   

                    //事件處理函數(shù)

                    public static  void MyEventHandler()

                    {

                        Console.WriteLine("This is a event!");

                    }

                }

               

            }

            首先寫(xiě)一個(gè)具有適當(dāng)形式的事件處理(通知)函數(shù) MyEventHandler,然后通過(guò)Obj.AEvent += newEventHandler(MyEventHandler)來(lái)定制事件。通過(guò)“-=”來(lái)撤消事件定制。

            運(yùn)行程序我們可以發(fā)現(xiàn),當(dāng)客戶(Class1)定制了Obj的AEvent事件后,在Obj的FireEvent()成員函數(shù)被調(diào)用時(shí),客戶可以在MyEventHandler函數(shù)中得到通知(在這里只是簡(jiǎn)單地輸出一個(gè)文本)。而當(dāng)客戶撤消該事件的定制后,就不會(huì)再得到該事件通知。

             

            二、C++版

            下面我們?cè)贑++中模擬該機(jī)制:

            由于C++不支持event關(guān)鍵字,我們就必須自己寫(xiě)代碼。在這里我通過(guò)模板類的手段來(lái)實(shí)現(xiàn),因?yàn)樵撌侄螌?shí)現(xiàn)的效果和C#比較類似。

            在VC6中新建一個(gè)win32 console app,命名為“cppevent“。新建一個(gè).h頭文件,命名為“event.h”,代碼如下:

            //event.h

             

            template <typename Handler>

            class event

            {

            private:

                     Handler m_Handler;

            protected:

                     //模擬C# event add/remove訪問(wèn)器

                     //如果要重新實(shí)現(xiàn)add/remove請(qǐng)?jiān)谂缮愔兄貙?xiě)這兩個(gè)函數(shù)

                     virtual void add(const Handler value){m_Handler = value;};

                     virtual void remove(const Handler value){if(value == m_Handler)m_Handler = NULL;};

            public:

                     //構(gòu)造函數(shù)

                     event():m_Handler(NULL){}

                     //+= 操作符

                     eventoperator += (const Handler value)

                     {

                               add(value);

                               return *this;

                     }

                     //-=操作符

                     eventoperator -= (const Handler value)

                     {

                               remove(value);

                               return *this;

                     }

                     //PFN_EVENT_HANDLE 操作符

                     operator Handler()

                     {

                               return m_Handler;

                     }

            };

             

            為了能夠在定義是指定事件處理函數(shù)的原型,我使用了template,為了能和C#一樣用+=-=來(lái)定制和撤消事件,我重載了這兩個(gè)操作符(C#不支持操作符重載),為了能像C#一樣直接把event當(dāng)做函數(shù)調(diào)用,我有重載了Handler自定義轉(zhuǎn)換操作符,可惜的是,這一點(diǎn)模擬得不是很像,在調(diào)用時(shí)還必須來(lái)一次強(qiáng)制轉(zhuǎn)換才可以:(,具體參看后面的代碼:

            C++版的MyClass如下:

            //MyClass.h

            #include "event.h"

            //定義EventHandler的函數(shù)指針類型

            typedef void(*EventHandler)();

             

            class MyClass

            {

            public:

                     //構(gòu)造函數(shù)

                     MyClass(){};

                     //聲明一個(gè)事件

                     event<EventHandlerAEvent;

                     //激發(fā)事件

                     void FireEvent()

                     {

                               if(AEvent != NULL)

                               {

                                        //C++中必須用EventHandler進(jìn)行強(qiáng)制類型轉(zhuǎn)換

                                        ((EventHandler)AEvent)();

                               };

                     }

             

            };

             

            C#版的MyClass比較一下你就會(huì)發(fā)現(xiàn)代碼非常接近,當(dāng)然,C#是在語(yǔ)言級(jí)直接支持event關(guān)鍵字的,而C++不支持,用模板類代替,所以聲明事件的代碼有些不一樣。還有就是FireEvent()C++不能把event對(duì)象直接當(dāng)做函數(shù)來(lái)調(diào)用,多了強(qiáng)制類型轉(zhuǎn)換。

             

            C++版的客戶代碼如下:

            // cppevent.cpp : Defines the entry point for the console application.

            //

             

            #include "stdafx.h"

            #include "MyClass.h"

            //向前聲明

            void MyEventHandler();

             

            int main(int argccharargv[])

            {

                     MyClass Obj;

                     Obj.AEvent += MyEventHandler;//定制事件

                     Obj.FireEvent();//這行將導(dǎo)致MyEventHandler被調(diào)用

             

                     Obj.AEvent -= MyEventHandler;//撤消事件

                     Obj.FireEvent();//這個(gè)將不會(huì)引發(fā)事件

             

             

                     printf("結(jié)束!/n");

                     char n;

                     scanf("%c", &n);

                     return 0;

            }

             

            void MyEventHandler()

            {

                     printf("This is a event!/n");

            }

             

            我們可以看到,可C#版的客戶代碼相比,核心部分是非常接近的,我們已經(jīng)可以和C#一樣用“+=”和“-=”來(lái)定制事件和撤消事件定制,并在ObjFireEvent()被調(diào)用時(shí)收到事件通知,輸出文本。

            鑒于篇幅的原因,我們沒(méi)有仔細(xì)比較兩個(gè)版本的eventaddremove訪問(wèn)器/成員函數(shù),其實(shí)二者也是非常類似的,你可以自己試試。C++版的eventaddremove均為virtual的,你可以從event類繼承出來(lái)一個(gè)MyEvent類,然后重新實(shí)現(xiàn)這兩個(gè)函數(shù),就可以定制自己的addremove了。這和C#add/remove訪問(wèn)器的也是非常相像的。

             

            三、總結(jié)

            通過(guò)這場(chǎng)“模仿show”我們可以從更深的層次理解C#event機(jī)制,更重要的是我們用自己所熟悉的東西(C++,模板類)來(lái)模仿并解釋了我們目前還不太熟悉的東西(C#event)。

            其實(shí),C#delegate就是C++的函數(shù)指針,C# event的核心機(jī)制就是C++中的模板(定義event時(shí)表現(xiàn)出來(lái))和運(yùn)算符重載(+=-=和直接把event當(dāng)做函數(shù)調(diào)用)的結(jié)合體。C#C++中容易出錯(cuò)的部分用“新特性”封裝了起來(lái),把這部分工作從programmer身上轉(zhuǎn)移到了compiler身上,讓我們把更多的精力集中到業(yè)務(wù)邏輯的處理上。

            <>

            posted on 2012-04-26 17:52 Dino-Tech 閱讀(628) 評(píng)論(0)  編輯 收藏 引用

            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            中文精品久久久久国产网址| 国内精品九九久久精品| 久久久无码精品亚洲日韩按摩 | 亚洲国产精品婷婷久久| 精品久久久久久国产免费了| 久久国产免费| 久久成人国产精品免费软件| 国产婷婷成人久久Av免费高清 | 久久久精品人妻无码专区不卡 | 亚洲精品NV久久久久久久久久| 狠狠综合久久综合88亚洲| 久久久精品一区二区三区| 国产精品久久久久久久久久影院 | 久久久久综合国产欧美一区二区 | 久久午夜福利无码1000合集| 精品国产91久久久久久久| 久久久久亚洲AV无码去区首| 久久精品中文无码资源站| 四虎国产精品免费久久| 中文字幕一区二区三区久久网站| 精品熟女少妇AV免费久久| 久久99亚洲综合精品首页| 国产精品女同久久久久电影院| 亚洲国产成人精品91久久久 | 午夜精品久久久内射近拍高清| 国内精品久久九九国产精品| 国内精品综合久久久40p| 日本久久久久久久久久| 久久久久国产一区二区 | 久久久久亚洲AV成人网人人网站| 欧美亚洲国产精品久久蜜芽| 伊人久久大香线焦AV综合影院 | 午夜精品久久久久久99热| 亚洲国产小视频精品久久久三级| 国产叼嘿久久精品久久| 亚洲成人精品久久| 国产69精品久久久久99| 大蕉久久伊人中文字幕| 精品99久久aaa一级毛片| 久久有码中文字幕| 欧美精品国产综合久久|