• <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>
            Creative Commons License
            本Blog采用 知識共享署名-非商業(yè)性使用-禁止演繹 3.0 Unported許可協(xié)議 進(jìn)行許可。 —— Fox <游戲人生>

            游戲人生

            游戲人生 != ( 人生 == 游戲 )
            站點(diǎn)遷移至:http://www.yulefox.com。請訂閱本博的朋友將RSS修改為http://feeds.feedburner.com/yulefox
            posts - 62, comments - 508, trackbacks - 0, articles - 7

            項(xiàng)目中使用了消息通信機(jī)制,因?yàn)橄㈩愋头浅6?,相?yīng)的,處理消息的地方代碼也非常多。

            自然而然想到MFC中的消息映射:

            創(chuàng)建一個(gè)缺省MFC框架程序的解決方案Test,在Test.h中看到以下內(nèi)容:

            class Ctest_mfcApp : public CWinApp
            {
            public:
                Ctest_mfcApp();

            // 重寫
            public:
                virtual BOOL InitInstance();

            // 實(shí)現(xiàn)
                afx_msg void OnAppAbout();
                DECLARE_MESSAGE_MAP()
            };

             

            其中,最緊要的就是DECLARE_MESSAGE_MAP()這個(gè)宏,相關(guān)內(nèi)容展開如下:

            struct AFX_MSGMAP_ENTRY
            {
                UINT nMessage;   // windows message
                UINT nCode;      // control code or WM_NOTIFY code
                UINT nID;        // control ID (or 0 for windows messages)
                UINT nLastID;    // used for entries specifying a range of control id's
                UINT_PTR nSig;   // signature type (action) or pointer to message #
                AFX_PMSG pfn;    // routine to call (or special value)
            };

            struct AFX_MSGMAP
            {
                const AFX_MSGMAP* (PASCAL* pfnGetBaseMap)();
                const AFX_MSGMAP_ENTRY* lpEntries;
            };

            #define DECLARE_MESSAGE_MAP() \
            protected: \
                static const AFX_MSGMAP* PASCAL GetThisMessageMap(); \
                virtual const AFX_MSGMAP* GetMessageMap() const; \

            其中AFX_PMSG不再解析下去,我們認(rèn)為這是一個(gè)指向特定消息對應(yīng)的實(shí)現(xiàn)函數(shù)的函數(shù)指針,這幾個(gè)宏的作用可簡單理解成為Test這個(gè)項(xiàng)目定義了一個(gè)靜態(tài)的消息映射表。當(dāng)消息到來時(shí),從消息隊(duì)列中彈出消息并分發(fā)到具有入口實(shí)現(xiàn)的上層CWnd派生窗口。用戶只需要注冊消息,實(shí)現(xiàn)消息入口函數(shù)就夠了,這在MFC中一般放在.cpp文件頭部。Test.cpp中頭部有以下內(nèi)容:

            BEGIN_MESSAGE_MAP(CTest, CWinApp)
                ON_COMMAND(ID_APP_ABOUT, &CTest::OnAppAbout)
                // 基于文件的標(biāo)準(zhǔn)文檔命令
                ON_COMMAND(ID_FILE_NEW, &CWinApp::OnFileNew)
                ON_COMMAND(ID_FILE_OPEN, &CWinApp::OnFileOpen)
                // 標(biāo)準(zhǔn)打印設(shè)置命令
                ON_COMMAND(ID_FILE_PRINT_SETUP, &CWinApp::OnFilePrintSetup)
            END_MESSAGE_MAP()

            這里是為消息枚舉值與消息實(shí)現(xiàn)函數(shù)建立映射,其中涉及到的宏的展開如下:

            #define ON_COMMAND(id, memberFxn) \
                { WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)id, AfxSigCmd_v, \
                    static_cast<AFX_PMSG> (memberFxn) },

            #define BEGIN_MESSAGE_MAP(theClass, baseClass) \
                PTM_WARNING_DISABLE \
                const AFX_MSGMAP* theClass::GetMessageMap() const \
                    { return GetThisMessageMap(); } \
                const AFX_MSGMAP* PASCAL theClass::GetThisMessageMap() \
                { \
                    typedef theClass ThisClass;                           \
                    typedef baseClass TheBaseClass;                       \
                    static const AFX_MSGMAP_ENTRY _messageEntries[] =  \
                    {

            #define END_MESSAGE_MAP() \
                    {0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } \
                }; \
                    static const AFX_MSGMAP messageMap = \
                    { &TheBaseClass::GetThisMessageMap, &_messageEntries[0] }; \
                    return &messageMap; \
                }                                  \
                PTM_WARNING_RESTORE

            按照上述思路得到的相似代碼如下:

            // Test.h
            typedef void (* funCall)(void*);        // 消息執(zhí)行函數(shù)類型

            struct tagMsgEntry                      // 消息入口結(jié)構(gòu)
            {
                int            nMsgType;            // 消息類型
                funCall        MsgRun;              // 消息執(zhí)行函數(shù)
            };

            struct tagMsgMap                        // 消息映射表結(jié)構(gòu)
            {
                const tagMsgMap* (__stdcall* funGetBaseMsgMap)();
                const tagMsgEntry* pMsgEntries;     // 消息入口集
            };

            class CMessage
            {
                // ...
            protected:
                static const tagMsgMap* __stdcall GetThisMsgMap();
                virtual const tagMsgMap* GetMsgMap() const;
            };

            // Test.cpp
            const tagMsgMap* CMessage::GetMsgMap() const
            {
                return GetThisMsgMap();
            }

            const tagMsgMap* __stdcall CMessage::GetThisMsgMap()
            {
                static const tagMsgEntry MsgEntries[] =
                {
                    { MSG_SOME_ONE, SomeOneFunc },
                    { MSG_SOME_TWO, SomeTwoFunc },
                    { MSG_NULL, NULL }
                };
                static const tagMsgMap msgMap =
                {
                    &CBaseMessage::GetThisMsgMap,    // 父類消息映射表
                    &MsgEntries[0]
                };
                return &msgMap;
            }

            int CMessage::MsgProc(int nMsgType)
            {
                switch( nMsgType )
                {
                case MSG_SOME_ONE:
                    {

                    }
                    break;
                }
                return CBaseMessage::MsgProc(nMsgType);
            }

            這種處理的優(yōu)點(diǎn)在于,子類沒有定義的消息實(shí)現(xiàn)接口,可以使用父類接口實(shí)現(xiàn)。不過在現(xiàn)在的消息處理中,我們一般不需要由基類來完成,因此可以不依賴基類接口,使用宏可以使代碼看上去更加簡潔。

            ___________________________________________________________

            簡化版本的消息映射采用以下方式,簡單清晰:

            // Test.h
            #define REG_MSG_FUNC(nMsgType, MsgFunc) \
                CMessge::RegisterCallFunc(nMsgType, MsgFunc); \

            typedef void (* function)(void*);

            typedef std::map<int, function> MSG_MAP;
            typedef MSG_MAP::const_iterator MSG_CITR;

            class CMessage
            {
                // ...
            public:
                static const MSG_MAP& GetMsgMap();
                static void RegisterCallFunc(int nMsgType, void(* Func)(void *))
                {
                    s_MsgMap[nMsgType] = Func;
                }

                int CMessage::Run(int nMsgType)                // 消息公用執(zhí)行函數(shù)
                {
                    MSG_ITR itr = s_MsgMap.find(nMsgType);
                    if( s_MsgMap.end() != itr )
                    {
                        itr->second(this);
                    }
                }

            protected:
                static MSG_MAP            s_MsgMap;            // 消息映射表
            };

            // UserTest.cpp -- 用戶在使用時(shí)對自己關(guān)心的消息予以注冊, 入口函數(shù)予以實(shí)現(xiàn)即可
            REG_MSG_FUNC(MSG_SOME_ONE, SomeOneFunc)

            void SomeOneFunc(CBaseMessage *pMsg)
            {
                return;
            }

            ___________________________________________________________

            最近忙的焦頭爛額,正好寫到消息,稍微整理一下,提供些許借鑒。

            Feedback

            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)[未登錄]  回復(fù)  更多評論   

            2008-09-30 12:32 by cppexplore
            頂一下
            前幾天我也剛寫了一個(gè),用在線程消息的處理中,我的消息類型做數(shù)組下標(biāo)了,直接定位取處理函數(shù),這都是無關(guān)緊要的細(xì)節(jié)。關(guān)鍵在ON_COMMAND宏的展現(xiàn)方式,我的處理線程消息,名字起做ON_MESSAGE
            整體思路基本都是一樣的,呵呵。

            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)  回復(fù)  更多評論   

            2008-10-10 08:50 by Condor
            對于成員函數(shù)這個(gè)寫法應(yīng)該沒用了。

            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)  回復(fù)  更多評論   

            2008-10-10 10:23 by Fox
            @Condor
            你說的這個(gè)問題我也考慮了,既然被提到,可以查看新一篇:http://www.shnenglu.com/Fox/archive/2008/10/10/63625.html

            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)  回復(fù)  更多評論   

            2009-02-18 02:30 by OwnWaterloo
            @cppexplore
            【消息類型做數(shù)組下標(biāo)了,直接定位取處理函數(shù),這都是無關(guān)緊要的細(xì)節(jié)?!?br>這恰恰是最重要的細(xì)節(jié) …… 這樣做得不償失……



            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)  回復(fù)  更多評論   

            2009-02-18 02:35 by OwnWaterloo
            @cppexplore
            我再說明白一點(diǎn):
            既然【用消息類型做數(shù)組下標(biāo),直接定位處理函數(shù)】,為什么不直接使用虛函數(shù)?

            你的方案是為了消息路由而消息路由,沒能理解采用消息路由的”苦衷“——如果采用更容易理解的虛函數(shù)來實(shí)現(xiàn),虛表將占用比較多的資源,不得已而采用消息路由。

            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)[未登錄]  回復(fù)  更多評論   

            2009-02-18 12:00 by cppexplore
            @OwnWaterloo
            歡迎來我blog討論:http://www.shnenglu.com/CppExplore 這篇http://www.shnenglu.com/CppExplore/archive/2008/11/07/66216.html下。查表是本質(zhì),為什么要使用虛函數(shù)?更容易理解?MFC的消息映射展現(xiàn)方式很難理解嗎? 虛函數(shù)更容易擴(kuò)展嗎? 說到虛函數(shù)占用較多資源而導(dǎo)致不得已采用消息路由,我不能認(rèn)同,這個(gè)因素在整個(gè)系統(tǒng)中的開銷你有沒有量化過?比如 因?yàn)椴捎盟鼘?dǎo)致并發(fā)數(shù)下降了多少多少之類?歡迎來我blog討論。

            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)  回復(fù)  更多評論   

            2009-02-18 16:29 by OwnWaterloo
            @cppexplore

            1. 時(shí)間消耗

            時(shí)間消耗自然不用說,是你的實(shí)現(xiàn)最得意的部分,o(1)。
            同樣,虛函數(shù)也是o(1)。

            2. 空間消耗

            假設(shè)你總共有N個(gè)消息,你仔細(xì)看看你的實(shí)現(xiàn):
            是不是每個(gè)(要處理消息的)類有一個(gè)長度會N的函數(shù)表,
            空間大小至少是N×sizeof(void*);
            每個(gè)對象有一個(gè)指向(或間接指向)該表的指針,
            空間大小至少是sizeof(void*)。

            虛函數(shù)的經(jīng)典實(shí)現(xiàn)的空間消耗也是one class one vtbl, one object one vptr,和你的實(shí)現(xiàn)還是相同的。


            這就回答了你一個(gè)問題:
            【我不能認(rèn)同,這個(gè)因素在整個(gè)系統(tǒng)中的開銷你有沒有量化過?比如 因?yàn)椴捎盟鼘?dǎo)致并發(fā)數(shù)下降了多少多少之類?】
            兩者的時(shí)間空間效率是完全一致的,即使我沒有量化過,也可以肯定,不會導(dǎo)致并發(fā)數(shù)下降。



            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)  回復(fù)  更多評論   

            2009-02-18 16:40 by OwnWaterloo
            @cppexplore

            【查表是本質(zhì)】
            這句你說到重點(diǎn)了,虛函數(shù)和你實(shí)現(xiàn)的那個(gè)還有哪些所謂的用C實(shí)現(xiàn)OO的,都是查表。

            【為什么要使用虛函數(shù)?更容易理解?MFC的消息映射展現(xiàn)方式很難理解嗎? 虛函數(shù)更容易擴(kuò)展嗎?】
            你這個(gè)實(shí)現(xiàn)就是在『模擬』虛函數(shù)。

            上面的時(shí)空分析,可以量化,我有把握你會同意我的觀點(diǎn)——兩者時(shí)空效率完全一樣——這個(gè)擴(kuò)展性嘛,不容易量化 ……

            你可以試著把你的實(shí)現(xiàn)用虛函數(shù)改寫一下(再次說明,時(shí)空效率完全一樣)??纯词欠裼X得虛函數(shù)更容易理解,更容易擴(kuò)展。



            btw:推薦你看看這個(gè),MFC會什么會采用消息映射而不是虛函數(shù)的理由,《C++多態(tài)技術(shù)的實(shí)現(xiàn)和反思》
            http://dev.yesky.com/189/2385189.shtml

            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)  回復(fù)  更多評論   

            2009-02-18 18:03 by OwnWaterloo
            @cppexplore

            再看了下你的實(shí)現(xiàn),好像我們討論的著重點(diǎn)不一樣。

            1. 你的系統(tǒng)里,是不是首先有這樣一個(gè)需求:
            因?yàn)槟撤N原因(分布式,進(jìn)程間,無鎖線程),消息的發(fā)送者不能直接調(diào)用消息處理函數(shù),而是傳送一個(gè)消息代碼來表示需要處理的類型?

            消息代碼即是win32中的WM_XX或者你的系統(tǒng)中的 enum MsgType { MSG_TYPE_1=65, ...  };



            2. 消息的處理者,又需要按照約定(即消息代碼的含義),將其映射到某個(gè)處理函數(shù)中。

            如 win32 中
            switch (message) {
            case WM_XXX:
               return OnXXX(hwnd,message,wparam,lparam);
            ...
            }

            或者你的系統(tǒng)中的
            switch(msg->type)
            {
                
            case MSG_TYPE_1:
                     do_msg_type_1_();
                     
            break;
                
            case MSG_TYPE_2:
                     do_msg_type_2_();
                     
            break;
                ..
                
            default:
                         do_default_msg_();
                         
            break;
            }



            在這一步,確實(shí)是你的實(shí)現(xiàn)方式時(shí)間效率比較高。
            但是在win32中, 這樣做不太現(xiàn)實(shí) ……  1000多個(gè)消息,表格就要包含1000多項(xiàng),而且大多都是DefWndProc。

            并且,在這一步中,虛函數(shù)根本就提供不了任何幫助。
            你的著重點(diǎn)在這一步?


            3. 你想實(shí)現(xiàn)一個(gè)消息處理者B,它對大多數(shù)消息的處理方式同A一樣,這時(shí)候如何盡可能的使用A的實(shí)現(xiàn)?
            (暫不說依賴于某實(shí)現(xiàn)是不太恰當(dāng)?shù)脑O(shè)計(jì),在MFC中多如牛毛……)

            我的著重點(diǎn)在這里,我對處理這步的觀點(diǎn)是: 『消息類型做數(shù)組下標(biāo)了,直接定位取處理函數(shù)』與『覆寫虛函數(shù)』相比,時(shí)空效率是相同的,我覺得后者更容易理解和擴(kuò)展。


            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)[未登錄]  回復(fù)  更多評論   

            2009-02-18 18:21 by cppexplore
            @OwnWaterloo
            怎么不直接去我blog回復(fù)呢 呵呵
            其實(shí) 時(shí)間消耗 之類并不是我最得意的東西,這種實(shí)現(xiàn)的細(xì)節(jié) 我并不太關(guān)注,所以質(zhì)疑你以前說的 “虛函數(shù)占用較多資源而導(dǎo)致不得已采用消息路由”,如何實(shí)現(xiàn)并不重要,關(guān)鍵的是容易理解,容易擴(kuò)展,容易維護(hù),容易移植,容易簡單化。
            win32 你是指win32 的界面設(shè)計(jì)? 業(yè)務(wù)系統(tǒng)里 基本不同的消息有不同的實(shí)現(xiàn),我的本意其實(shí)都不在實(shí)現(xiàn),而在于簡單的思想,因此是查表實(shí)現(xiàn) 還是虛函數(shù)實(shí)現(xiàn) 也都無所謂,只要最后有統(tǒng)一的擴(kuò)展方式。

            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)[未登錄]  回復(fù)  更多評論   

            2009-02-18 18:55 by cppexplore
            @OwnWaterloo
            呵呵,最后的問題歸結(jié)為:哪種更容易理解和擴(kuò)展。
            超大工程當(dāng)然是數(shù)組方式之上用宏展現(xiàn)最容易理解和擴(kuò)展了,簡潔直接。幾十w行的代碼,用虛函數(shù),文件數(shù)量的迅速膨脹 找個(gè)東西都找不到在哪里,所有東西交織錯(cuò)亂在一起,最終維護(hù)程序的人都會想:要是有張表就好了,只看表就知道那個(gè)函數(shù)處理哪個(gè)消息,而宏的展現(xiàn)就是如此。 當(dāng)然如果用宏包裹下虛函數(shù)的實(shí)現(xiàn),結(jié)果就一樣了。
            并且數(shù)組表只是一個(gè)思路,不攜帶任何面向?qū)ο蟮恼Z義,在這個(gè)業(yè)務(wù)系統(tǒng)里可用,在那個(gè)業(yè)務(wù)系統(tǒng)里也可用,虛函數(shù)有這么好的移植性嗎?有這么簡單化嗎?

            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)  回復(fù)  更多評論   

            2009-02-19 01:57 by OwnWaterloo
            @cppexplore
            【怎么不直接去我blog回復(fù)呢 呵呵】
            好像是cppblog對url的分析有點(diǎn)問題,這個(gè)url: http://www.shnenglu.com/CppExplore/archive/2008/11/07/66216.html
            會被截取,只將前面一部分(也就是你的主頁)制作成鏈接,點(diǎn)過去沒看見什么文章……
            后來才發(fā)現(xiàn)這個(gè)問題,找到那篇文章……
            【容易理解,容易擴(kuò)展,容易維護(hù),容易移植,容易簡單化】
            嗯,這是重點(diǎn)。同時(shí)我也贊同你文章里最后一句話【一句話:重要的是思想,不是平臺和語言?!?br> 
            "你的實(shí)現(xiàn)就是模擬C++虛函數(shù)的經(jīng)典實(shí)現(xiàn)",這個(gè)觀點(diǎn)你贊同嗎?
            你的系統(tǒng)需要考慮向C(以及不支持虛函數(shù)的語言)移植嗎?
             
            如果贊同且不需要,那么繼續(xù)討論理解擴(kuò)展維護(hù)、簡單。
            你的系統(tǒng)具體要做什么不太了解,我用win32作例子可以嗎?比如,現(xiàn)在需要關(guān)心的消息只有2個(gè):
            enum MsgType {
                WM__LBUTTONDOWN 
            /*= 0*/,
                WM__SIZING,
                
            // 
            };
            struct Msg {
                MsgType type;
                HWND    hwnd;
                WPARAM  wparam;
                LPARAM  lparam;
            };

            如果使用C++虛函數(shù)機(jī)制:
             
            class IHandler {
            public:
                
            virtual ~IHandler() {};
            protected:
                
            virtual void OnLButtonDown(POINTS pt,bool ctrl,bool shift,bool l,bool m,bool r) = 0 {};
                
            virtual void OnSizing(RECT& rc,int side) = 0 {};
            public:
                LRESULT Do(Msg
            * msg) {
                    
            switch (msg->type) {
                        
            case WM__LBUTTONDOWN:
                            OnLButtonDown(MAKEPOINTS(msg
            ->lparam)
                                         ,msg
            ->wparam & MK_CONTROL
                                         ,msg
            ->wparam & MK_SHIFT
                                         ,msg
            ->wparam & MK_LBUTTON
                                         ,msg
            ->wparam & MK_MBUTTON
                                         ,msg
            ->wparam & MK_RBUTTON);
                            
            return 0;
                        
            case WM__SIZING:
                            OnSizing(
            *reinterpret_cast<RECT*>(msg->lparam),msg->wparam);
                            
            return 0;
                    }

                    
            return DefWindowProc(msg->hwnd,msg->type,msg->wparam,msg->lparam);
                }

            }
            ;
             
            具體的消息處理類可以這樣:
            class Handler1 : public IHandler {
                
            void OnLButtonDown(POINTS pt,bool ctrl,bool shift,bool l,bool m,bool r) {
                    IHandler::OnLButtonDown(pt,ctrl,shift,l,m,r);
                }

                
            void OnSizing(RECT& rc,int side) {
                    IHandler::OnSizing(rc,side);
                }

            }
            ;
             
            上面的基類的虛函數(shù)帶有默認(rèn)實(shí)現(xiàn),但設(shè)置為純虛函數(shù)。
            具體類必須實(shí)現(xiàn)每個(gè)消息處理過程,如果不關(guān)心,可以簡單使用基類實(shí)現(xiàn)。
            另一種方式:基類提供默認(rèn)實(shí)現(xiàn),并且不是純虛函數(shù);具體類只需覆寫關(guān)心的消息。
             
            另一方面,上面的基類沒有使用表格,如果覺得switch case 不好維護(hù),也可以使用表格。
             
            兩方面都采用另一種方案的話,基類就如下:
            class IHandler {
            public:
                
            virtual ~IHandler() {};
            private:
                
            virtual void OnLButtonDown(POINTS pt,bool ctrl,bool shift,bool l,bool m,bool r)  {};
                
            virtual void OnSizing(RECT& rc,int side)  {};
            public:
                LRESULT Do(Msg
            * msg) {
                    assert(msg
            ->type>=0 && msg->type<WM__SIZING);
                    
            return MsgProcs[msg->type](msg->hwnd,msg->type,msg->wparam,msg->lparam,this);
                }


            private:
                typedef LRESULT (
            *MsgProc)(HWND,MsgType,WPARAM,LPARAM,IHandler* handler);
                
            const static MsgProc MsgProcs[];
                
            static LRESULT OnLButtonDown(HWND,MsgType,WPARAM wparam,LPARAM lparam,IHandler* handler) {
                    handler
            ->OnLButtonDown(MAKEPOINTS(lparam)
                                          ,wparam 
            & MK_CONTROL
                                          ,wparam 
            & MK_SHIFT
                                          ,wparam 
            & MK_LBUTTON
                                          ,wparam 
            & MK_MBUTTON
                                          ,wparam 
            & MK_RBUTTON);
                    
            return 0;
                }

                
            static LRESULT OnSizing(HWND,MsgType,WPARAM wparam,LPARAM lparam,IHandler* handler) {
                    handler
            ->OnSizing(*reinterpret_cast<RECT*>(lparam),wparam);
                    
            return 0;
                }

            }
            ;

            const IHandler::MsgProc IHandler::MsgProcs[] = {
                IHandler::OnLButtonDown,
                IHandler::OnSizing,
            }
            ;

            具體類的編寫就更簡單: 假設(shè)僅關(guān)心OnLButtonDown
            class Handler1 : public IHandler {
                
            void OnLButtonDown(POINTS pt,bool ctrl,bool shift,bool l,bool m,bool r) {
                    printf(
            "(%d,%d) ctrl=%d,shitf=%d\n",pt.x,pt.y,ctrl,shift);
                }

            }
            ;

             

            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)  回復(fù)  更多評論   

            2009-02-19 02:16 by OwnWaterloo
                                          考慮擴(kuò)展
             
            添加一個(gè)新的消息處理類。
            如果基類不是純虛函數(shù),那最簡單了,覆寫需要關(guān)心的消息就可以了。
            如果是純虛函數(shù),需要實(shí)現(xiàn)所有消息處理函數(shù),對不關(guān)心的消息,使用基類默認(rèn)處理。
             
            而你的方案,不得不將所有的消息都映射一遍——因?yàn)椤鞠㈩愋妥鰯?shù)組下標(biāo),直接定位取處理函數(shù)】——即使不關(guān)心而作一個(gè)空函數(shù)。 
            BEGIN_MESSAGE_MAP(SessionManager,SessionMsg)
                ON_MESSAGE(MSG_TYPE_1, SessionManager::do_msg_type_1_)
                ON_MESSAGE(MSG_TYPE_2, SessionManager::do_msg_type_2_)
                
            // .. MORE
            END_MESSAGE_MAP()
            如果不是這樣,請務(wù)必告訴我你是怎么不使用虛函數(shù)實(shí)現(xiàn)的。
             
             
            添加一個(gè)新的消息種類(消息代碼)
            如果可以保證消息代碼連續(xù),可以使用上面的方案2,在表格中多加入一條。
            如果不能保證消息代碼連續(xù)(并且非常稀疏),就只能采用swtich case。
             
            已經(jīng)編寫好的具體的消息處理類,如果都可以安全忽略該消息,那么可以采用上面的方案2——基類有默認(rèn)實(shí)現(xiàn)且不純虛——那么除了基類,已經(jīng)編寫好的具體類都不需要修改。
            如果不全都可以安全忽略該消息,那么可以采用上面的方案1——基類有空實(shí)現(xiàn),但是純虛——具類中可以忽略該消息的,使用基類實(shí)現(xiàn),不能忽略的,編寫處理函數(shù)。
             
            而你的方案,一旦添加一個(gè)新的消息處理代碼(同時(shí)要保證連續(xù)),所有的消息處理類都必須在其表格中增加一項(xiàng)。

            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)  回復(fù)  更多評論   

            2009-02-19 02:16 by OwnWaterloo
            移植性確實(shí)會在不支持虛函數(shù)的語言中完敗。
            論理解、擴(kuò)展、維護(hù)、簡單的話,你現(xiàn)在仍然覺得虛函數(shù)比不上表格嗎?

            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)[未登錄]  回復(fù)  更多評論   

            2009-02-19 10:16 by cppexplore
            @OwnWaterloo
            呵呵 你覺得你的想法來源于面向?qū)ο蟮募埳险劚]有貶義)以及基于win32的mfc框架程序設(shè)計(jì)。
            我的實(shí)現(xiàn)不是為了模擬虛函數(shù)的實(shí)現(xiàn),只是為了實(shí)現(xiàn)一個(gè)易維護(hù)的消息映射而已。
            首先 對象A不能直接向?qū)ο驜直接發(fā)送消息,需要調(diào)用對象B的ON_send_msg,由B自己的方法向自己發(fā)送消息,由B的DO_Msg方法處理消息,當(dāng)然發(fā)送動作和處理動作在不同的線程內(nèi)。任何對象向B發(fā)送消息都要調(diào)用B自己的方法。也就是說對象B的具體消息類型對其它對象是不可見的。
            因此對象B中的消息類型是連續(xù)的,并且不存在自己不感興趣的消息,既然不感興趣,就不會存在這個(gè)消息類型,只要是存在的就是感興趣的,就是要處理的。也不存在對多個(gè)消息,處理方式相同的問題,既然處理方式相同,它們就是同一個(gè)消息。
            其次 你還是回避了大型程序開發(fā)中,使用虛函數(shù)方式,文件個(gè)數(shù)膨脹的問題。
            最后 我討論的是線程間的消息傳遞和映射,你的有偏向于 已經(jīng)發(fā)送到UI線程的消息,對責(zé)任鏈模式上的 各個(gè)對象的后續(xù)處理。

            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)  回復(fù)  更多評論   

            2009-02-19 22:42 by OwnWaterloo
            @cppexplore

            第1個(gè)疑問:
            系統(tǒng)中所有類使用的消息代碼是否是同一套?都是
            enum MsgType
            {
            MSG_TYPE_1=65,//64一下預(yù)留,用于統(tǒng)一的管理控制
            MSG_TYPE_2,
            ..
            MSG_TYPE_MAX
            };
            ???

            第2個(gè)疑問:(同時(shí)也是回答)
            確實(shí)如你所說,我是【紙上談兵】。
            我沒有【大型程序】的開發(fā)經(jīng)驗(yàn),更是不能理解:
            【大型程序開發(fā)中,使用虛函數(shù)方式,文件個(gè)數(shù)膨脹的問題?!?br>這是為什么? 請指教~~~ 昨天就想問你了,字打多了就忘了……

            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)[未登錄]  回復(fù)  更多評論   

            2009-02-19 22:51 by cppexplore
            @OwnWaterloo
            不是同一套,只有64以下的是相同。64以上的各個(gè)線程之間可以重復(fù),因?yàn)閷ζ渌麑ο笫遣豢梢姷?,所以不存在沖突問題。可以定義USER_MSG_START=64.
            項(xiàng)目越大,越需要表格,容易維護(hù),容易擴(kuò)展,容易找對應(yīng)關(guān)系,也就是看一個(gè)文件就知道所有,而不是在幾十個(gè)上百個(gè)文件里查找。當(dāng)然要看你的虛函數(shù)實(shí)現(xiàn)成什么樣子了。
            我舉的例子,對象B是管理類,同時(shí)也是線程類。里面管理了很多的對象,B拿到消息也是找到對應(yīng)的對象去處理,貌似你一直談的是后續(xù)。
            而你在MFC里看到的是同一套,那是因?yàn)樗鼈兌荚赨I線程里,同屬于一個(gè)線程,一個(gè)管理類。

            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)  回復(fù)  更多評論   

            2009-02-19 23:23 by OwnWaterloo
            @cppexplore
            我覺得加QQ聊會快一點(diǎn)…… “六久久思武柳留靈”

            不是同一套,那么A向B發(fā)一個(gè)65以上的消息,B如何知道代表什么含義呢?
            要么:A只向B發(fā)64以下的消息。
            要么:存在T1,T2, ... Tn個(gè)線程,每個(gè)線程下分別有
            A11,A12, ... An1...
            A21,A22, ... An2...
            ...
            A[i][j]只會和A[i][k]直接交互
            A[i][j]和A[k][l]通過某種機(jī)制間接交互



            -----------------------------
            【貌似你一直談的是后續(xù)。 】
            可能是這樣的,我在
            http://www.shnenglu.com/Fox/archive/2008/09/29/63056.aspx#74178
            也說了。

            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)[未登錄]  回復(fù)  更多評論   

            2009-02-20 10:19 by cppexplore
            @OwnWaterloo
            上班不能qq 呵呵 下班加你
            A不能以指定消息值的方式向B發(fā)消息,通過調(diào)用B自身的ON_MSG方法發(fā)送。也就是除了B自己,誰也不知道它具體消息的枚舉值。
            64一下的也是調(diào)用B自身的方法發(fā)送,不過這些是B基類中的方法。

            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)  回復(fù)  更多評論   

            2011-10-15 16:04 by
            人 需要一種簡單的 東西來支撐屬于自身內(nèi)心的簡單,這樣的簡單一直以來是無形的,就如同所有存在的 對于支撐簡單的東西已經(jīng) 進(jìn)行過的時(shí)候,那么內(nèi)心當(dāng)中還是缺少對于無法割舍的簡單的 內(nèi)涵

            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)  回復(fù)  更多評論   

            2011-10-15 16:06 by
            在某一種環(huán)境下面其實(shí)簡單的來說在于一旦沒有了這樣的一種現(xiàn)實(shí),簡單的環(huán)境是否在可能變化的環(huán)境當(dāng)中產(chǎn)生簡單的過程那樣如此簡單明了

            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)  回復(fù)  更多評論   

            2011-10-15 16:07 by
            所以自己的內(nèi)心真誠的東西不是對于某一種勢力的那種附和,而是對于在這個(gè)過程當(dāng)中自身能夠決定進(jìn)入某一種勢力需要的那種條件的 認(rèn)可

            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)  回復(fù)  更多評論   

            2011-10-15 16:08 by
            在各種各樣的 范圍內(nèi)決定一個(gè)人能夠簡單的進(jìn)行自身的活動范圍內(nèi) 并且 能夠達(dá)到一些盡可能需要的行為內(nèi),需要的不僅僅是可靠性的 過程,更重要的是價(jià)值活動的產(chǎn)生

            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)  回復(fù)  更多評論   

            2011-10-15 16:09 by
            在過程行為當(dāng)中能夠明確的 在于是已經(jīng)形成出來的新的一種競爭力自身需要的一種內(nèi)心活動 當(dāng)中產(chǎn)生的角色轉(zhuǎn)換的 過程當(dāng)中需要的互動意識與能力

            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)  回復(fù)  更多評論   

            2011-10-15 16:10 by
            因此各種各樣的簡單絕對不是取決于自身在竭盡全力自后需要的條件,而是自身竭盡全力的過程當(dāng)中自己需要的休息的素質(zhì)與能力的那種背景考量的能力

            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)  回復(fù)  更多評論   

            2012-04-16 09:10 by
            基本上來說一個(gè)人成熟的機(jī)制恐怕是能夠讓自己能夠在不斷的磨合當(dāng)中逐漸消失成見的過程,就一個(gè)成熟的那種業(yè)績體系來說,實(shí)際上現(xiàn)在的復(fù)雜在于業(yè)績對象的那種針對的安全對象的成熟度沒有,如果僅僅針對的是一種瘋子般的業(yè)務(wù)來說的業(yè)績或者組織層面來說的業(yè)績,這樣的機(jī)制成熟的業(yè)績體系是不存在的一個(gè)方式。

            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)  回復(fù)  更多評論   

            2012-04-16 09:13 by
            實(shí)際上業(yè)績組合套拳的組合一定夾雜某一種對于私心認(rèn)可的范疇內(nèi)達(dá)到的應(yīng)急范疇內(nèi)實(shí)現(xiàn)對于業(yè)績整個(gè)機(jī)制的認(rèn)識,從表面上來看,一旦業(yè)績沒有屬于自己范圍的業(yè)績過程,整個(gè)的業(yè)績鏈被居心叵測的人所掌握,那么業(yè)績機(jī)制上面的成熟機(jī)制在實(shí)現(xiàn)的過程永遠(yuǎn)被這樣或者那樣的理由所圈繞。一個(gè)成熟的業(yè)績機(jī)體本身上面是由于其中業(yè)績機(jī)體上面有按照其中規(guī)律方式運(yùn)轉(zhuǎn)的模式旋轉(zhuǎn),而與時(shí)代與行業(yè),和管理它的人就更加沒有關(guān)系的了

            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)  回復(fù)  更多評論   

            2012-04-16 09:16 by
            業(yè)績機(jī)制上面的成熟度在于在不斷的磨合的組合的過程當(dāng)中永遠(yuǎn)不可能按照面上面的業(yè)績組合形成業(yè)績機(jī)制過程,業(yè)績機(jī)制表明的是在業(yè)績最初形成的時(shí)候,需要使用各種各樣關(guān)于技巧性的使用,一旦業(yè)績成熟,則不過是一種對于業(yè)績形成上面需要依照的規(guī)律模式行駛其中業(yè)績機(jī)制形成的規(guī)律線而已。

            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)  回復(fù)  更多評論   

            2012-04-16 09:19 by
            業(yè)績機(jī)制形成的規(guī)律線絕對不是建立在回復(fù)其它層面的上面的不斷的 解釋層次上面表現(xiàn)出來的那種心安理得局面上面的業(yè)績機(jī)制,業(yè)績機(jī)制的形成在于自己認(rèn)為需要付出多少的代價(jià)愿意承受這樣的一種業(yè)績機(jī)制的形成,業(yè)績機(jī)制的形成一般是競爭分析--競爭對手分析---柜臺分析---賺錢分析---承載風(fēng)險(xiǎn)分析---合理的業(yè)績軌道,這個(gè)業(yè)績機(jī)制的形成在于一旦在那種對于業(yè)績本身模式不認(rèn)可,而且浮于人事層面上面是永遠(yuǎn)不可能體會 到這樣的一個(gè)業(yè)績機(jī)制形成的過程的。

            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)  回復(fù)  更多評論   

            2012-04-16 09:22 by
            基于對于業(yè)績機(jī)制形成的事實(shí),然后規(guī)劃屬于自身現(xiàn)狀的業(yè)績狀況就能夠發(fā)現(xiàn),充分的運(yùn)用屬于自己的認(rèn)識與人事與實(shí)力來驗(yàn)證對于業(yè)績機(jī)制的本身帶來的效果,然后再這樣的一種效果當(dāng)中明確這樣的一種業(yè)績機(jī)制承載出來一個(gè)怎么樣的自己的體驗(yàn)當(dāng)中,從而對于自己有一個(gè)或者有一種全新的認(rèn)識的過程,至少在這個(gè)過程當(dāng)中,能夠承載屬于自己職業(yè)生命力的安全模式

            # re: 消息映射機(jī)制的簡單實(shí)現(xiàn)  回復(fù)  更多評論   

            2012-04-16 09:25 by
            確切的說,業(yè)績機(jī)制承載的職業(yè)生命力具體表現(xiàn)在屬于一種胸襟,沒有一種胸襟,格局的誕生恐怕只能夠越來越小,胸襟不是以職業(yè)生命力的安全作為安全,而恰恰相反,胸襟是站在或者基于職業(yè)生命力維護(hù)的基礎(chǔ)上面去考慮胸襟本身的得失或者愿意承受的東西和不愿意承受的順應(yīng)心靈的一種呼喚。
            日韩欧美亚洲综合久久影院Ds | 久久久不卡国产精品一区二区| 波多野结衣中文字幕久久| 2021少妇久久久久久久久久| 久久综合中文字幕| 亚洲精品国精品久久99热| 性做久久久久久久| 办公室久久精品| 久久亚洲精品国产精品| 久久精品国产清自在天天线| 浪潮AV色综合久久天堂| 精品久久久久中文字幕一区| 久久精品国产亚洲AV影院 | 久久久WWW成人免费毛片| 久久亚洲AV成人无码软件| 人妻精品久久无码专区精东影业| 国产午夜精品理论片久久| 97精品依人久久久大香线蕉97 | segui久久国产精品| 久久中文字幕人妻丝袜| 精品久久久久久无码人妻热| 久久久老熟女一区二区三区| 四虎国产精品成人免费久久| 99久久精品国产一区二区| 蜜臀av性久久久久蜜臀aⅴ麻豆| 蜜桃麻豆www久久国产精品| 久久久精品免费国产四虎| 国内精品伊人久久久久av一坑 | 精品无码人妻久久久久久| 97久久久精品综合88久久| 亚洲人成无码久久电影网站| 999久久久免费国产精品播放| 久久久久久夜精品精品免费啦| 久久精品国产亚洲av麻豆蜜芽| 久久久久国色AV免费观看| Xx性欧美肥妇精品久久久久久| 久久久久中文字幕| 久久婷婷国产麻豆91天堂| 热99re久久国超精品首页| 久久最近最新中文字幕大全 | 99国产欧美精品久久久蜜芽|