• <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采用 知識共享署名-非商業性使用-禁止演繹 3.0 Unported許可協議 進行許可。 —— Fox <游戲人生>

            游戲人生

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

            消息映射機制的簡單實現

            Posted on 2008-09-29 18:34 Fox 閱讀(4492) 評論(31)  編輯 收藏 引用 所屬分類: T技術碎語

            項目中使用了消息通信機制,因為消息類型非常多,相應的,處理消息的地方代碼也非常多。

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

            創建一個缺省MFC框架程序的解決方案Test,在Test.h中看到以下內容:

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

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

            // 實現
                afx_msg void OnAppAbout();
                DECLARE_MESSAGE_MAP()
            };

             

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

            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不再解析下去,我們認為這是一個指向特定消息對應的實現函數的函數指針,這幾個宏的作用可簡單理解成為Test這個項目定義了一個靜態的消息映射表。當消息到來時,從消息隊列中彈出消息并分發到具有入口實現的上層CWnd派生窗口。用戶只需要注冊消息,實現消息入口函數就夠了,這在MFC中一般放在.cpp文件頭部。Test.cpp中頭部有以下內容:

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

            這里是為消息枚舉值與消息實現函數建立映射,其中涉及到的宏的展開如下:

            #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*);        // 消息執行函數類型

            struct tagMsgEntry                      // 消息入口結構
            {
                int            nMsgType;            // 消息類型
                funCall        MsgRun;              // 消息執行函數
            };

            struct tagMsgMap                        // 消息映射表結構
            {
                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);
            }

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

            ___________________________________________________________

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

            // 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)                // 消息公用執行函數
                {
                    MSG_ITR itr = s_MsgMap.find(nMsgType);
                    if( s_MsgMap.end() != itr )
                    {
                        itr->second(this);
                    }
                }

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

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

            void SomeOneFunc(CBaseMessage *pMsg)
            {
                return;
            }

            ___________________________________________________________

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

            Feedback

            # re: 消息映射機制的簡單實現[未登錄]  回復  更多評論   

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

            # re: 消息映射機制的簡單實現  回復  更多評論   

            2008-10-10 08:50 by Condor
            對于成員函數這個寫法應該沒用了。

            # re: 消息映射機制的簡單實現  回復  更多評論   

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

            # re: 消息映射機制的簡單實現  回復  更多評論   

            2009-02-18 02:30 by OwnWaterloo
            @cppexplore
            【消息類型做數組下標了,直接定位取處理函數,這都是無關緊要的細節。】
            這恰恰是最重要的細節 …… 這樣做得不償失……



            # re: 消息映射機制的簡單實現  回復  更多評論   

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

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

            # re: 消息映射機制的簡單實現[未登錄]  回復  更多評論   

            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下。查表是本質,為什么要使用虛函數?更容易理解?MFC的消息映射展現方式很難理解嗎? 虛函數更容易擴展嗎? 說到虛函數占用較多資源而導致不得已采用消息路由,我不能認同,這個因素在整個系統中的開銷你有沒有量化過?比如 因為采用它導致并發數下降了多少多少之類?歡迎來我blog討論。

            # re: 消息映射機制的簡單實現  回復  更多評論   

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

            1. 時間消耗

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

            2. 空間消耗

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

            虛函數的經典實現的空間消耗也是one class one vtbl, one object one vptr,和你的實現還是相同的。


            這就回答了你一個問題:
            【我不能認同,這個因素在整個系統中的開銷你有沒有量化過?比如 因為采用它導致并發數下降了多少多少之類?】
            兩者的時間空間效率是完全一致的,即使我沒有量化過,也可以肯定,不會導致并發數下降。



            # re: 消息映射機制的簡單實現  回復  更多評論   

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

            【查表是本質】
            這句你說到重點了,虛函數和你實現的那個還有哪些所謂的用C實現OO的,都是查表。

            【為什么要使用虛函數?更容易理解?MFC的消息映射展現方式很難理解嗎? 虛函數更容易擴展嗎?】
            你這個實現就是在『模擬』虛函數。

            上面的時空分析,可以量化,我有把握你會同意我的觀點——兩者時空效率完全一樣——這個擴展性嘛,不容易量化 ……

            你可以試著把你的實現用虛函數改寫一下(再次說明,時空效率完全一樣)。看看是否覺得虛函數更容易理解,更容易擴展。



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

            # re: 消息映射機制的簡單實現  回復  更多評論   

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

            再看了下你的實現,好像我們討論的著重點不一樣。

            1. 你的系統里,是不是首先有這樣一個需求:
            因為某種原因(分布式,進程間,無鎖線程),消息的發送者不能直接調用消息處理函數,而是傳送一個消息代碼來表示需要處理的類型?

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



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

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

            或者你的系統中的
            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;
            }



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

            并且,在這一步中,虛函數根本就提供不了任何幫助
            你的著重點在這一步?


            3. 你想實現一個消息處理者B,它對大多數消息的處理方式同A一樣,這時候如何盡可能的使用A的實現?
            (暫不說依賴于某實現是不太恰當的設計,在MFC中多如牛毛……)

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


            # re: 消息映射機制的簡單實現[未登錄]  回復  更多評論   

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

            # re: 消息映射機制的簡單實現[未登錄]  回復  更多評論   

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

            # re: 消息映射機制的簡單實現  回復  更多評論   

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

            如果使用C++虛函數機制:
             
            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);
                }

            }
            ;
             
            上面的基類的虛函數帶有默認實現,但設置為純虛函數。
            具體類必須實現每個消息處理過程,如果不關心,可以簡單使用基類實現。
            另一種方式:基類提供默認實現,并且不是純虛函數;具體類只需覆寫關心的消息。
             
            另一方面,上面的基類沒有使用表格,如果覺得switch case 不好維護,也可以使用表格。
             
            兩方面都采用另一種方案的話,基類就如下:
            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,
            }
            ;

            具體類的編寫就更簡單: 假設僅關心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: 消息映射機制的簡單實現  回復  更多評論   

            2009-02-19 02:16 by OwnWaterloo
                                          考慮擴展
             
            添加一個新的消息處理類。
            如果基類不是純虛函數,那最簡單了,覆寫需要關心的消息就可以了。
            如果是純虛函數,需要實現所有消息處理函數,對不關心的消息,使用基類默認處理。
             
            而你的方案,不得不將所有的消息都映射一遍——因為【消息類型做數組下標,直接定位取處理函數】——即使不關心而作一個空函數。 
            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()
            如果不是這樣,請務必告訴我你是怎么不使用虛函數實現的。
             
             
            添加一個新的消息種類(消息代碼)
            如果可以保證消息代碼連續,可以使用上面的方案2,在表格中多加入一條。
            如果不能保證消息代碼連續(并且非常稀疏),就只能采用swtich case。
             
            已經編寫好的具體的消息處理類,如果都可以安全忽略該消息,那么可以采用上面的方案2——基類有默認實現且不純虛——那么除了基類,已經編寫好的具體類都不需要修改
            如果不全都可以安全忽略該消息,那么可以采用上面的方案1——基類有空實現,但是純虛——具類中可以忽略該消息的,使用基類實現,不能忽略的,編寫處理函數。
             
            而你的方案,一旦添加一個新的消息處理代碼(同時要保證連續),所有的消息處理類都必須在其表格中增加一項。

            # re: 消息映射機制的簡單實現  回復  更多評論   

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

            # re: 消息映射機制的簡單實現[未登錄]  回復  更多評論   

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

            # re: 消息映射機制的簡單實現  回復  更多評論   

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

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

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

            # re: 消息映射機制的簡單實現[未登錄]  回復  更多評論   

            2009-02-19 22:51 by cppexplore
            @OwnWaterloo
            不是同一套,只有64以下的是相同。64以上的各個線程之間可以重復,因為對其他對象是不可見得,所以不存在沖突問題。可以定義USER_MSG_START=64.
            項目越大,越需要表格,容易維護,容易擴展,容易找對應關系,也就是看一個文件就知道所有,而不是在幾十個上百個文件里查找。當然要看你的虛函數實現成什么樣子了。
            我舉的例子,對象B是管理類,同時也是線程類。里面管理了很多的對象,B拿到消息也是找到對應的對象去處理,貌似你一直談的是后續。
            而你在MFC里看到的是同一套,那是因為它們都在UI線程里,同屬于一個線程,一個管理類。

            # re: 消息映射機制的簡單實現  回復  更多評論   

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

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



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

            # re: 消息映射機制的簡單實現[未登錄]  回復  更多評論   

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

            # re: 消息映射機制的簡單實現  回復  更多評論   

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

            # re: 消息映射機制的簡單實現  回復  更多評論   

            2011-10-15 16:06 by
            在某一種環境下面其實簡單的來說在于一旦沒有了這樣的一種現實,簡單的環境是否在可能變化的環境當中產生簡單的過程那樣如此簡單明了

            # re: 消息映射機制的簡單實現  回復  更多評論   

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

            # re: 消息映射機制的簡單實現  回復  更多評論   

            2011-10-15 16:08 by
            在各種各樣的 范圍內決定一個人能夠簡單的進行自身的活動范圍內 并且 能夠達到一些盡可能需要的行為內,需要的不僅僅是可靠性的 過程,更重要的是價值活動的產生

            # re: 消息映射機制的簡單實現  回復  更多評論   

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

            # re: 消息映射機制的簡單實現  回復  更多評論   

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

            # re: 消息映射機制的簡單實現  回復  更多評論   

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

            # re: 消息映射機制的簡單實現  回復  更多評論   

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

            # re: 消息映射機制的簡單實現  回復  更多評論   

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

            # re: 消息映射機制的簡單實現  回復  更多評論   

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

            # re: 消息映射機制的簡單實現  回復  更多評論   

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

            # re: 消息映射機制的簡單實現  回復  更多評論   

            2012-04-16 09:25 by
            確切的說,業績機制承載的職業生命力具體表現在屬于一種胸襟,沒有一種胸襟,格局的誕生恐怕只能夠越來越小,胸襟不是以職業生命力的安全作為安全,而恰恰相反,胸襟是站在或者基于職業生命力維護的基礎上面去考慮胸襟本身的得失或者愿意承受的東西和不愿意承受的順應心靈的一種呼喚。
            久久亚洲熟女cc98cm| 久久91精品国产91久久麻豆| 久久国产精品成人免费| 精品久久久无码人妻中文字幕 | 999久久久国产精品| 人妻无码久久一区二区三区免费 | 一本伊大人香蕉久久网手机| 久久精品国产亚洲AV香蕉| 亚洲精品午夜国产VA久久成人| 99久久无色码中文字幕人妻| 久久99热这里只频精品6| 777午夜精品久久av蜜臀| 国产精品久久久久jk制服| 久久久久久午夜成人影院| 久久国产精品-久久精品| 国内精品久久久久久中文字幕| 久久精品成人免费国产片小草| 亚洲国产成人久久综合区| 久久天天躁狠狠躁夜夜2020一| 色婷婷久久综合中文久久蜜桃av| 99久久免费国产精品热| 热久久这里只有精品| 亚洲&#228;v永久无码精品天堂久久| 欧美伊人久久大香线蕉综合69| 久久人人爽人人爽人人片av麻烦 | 99久久国产综合精品成人影院| 久久精品国产99国产精品| 亚洲国产精品成人久久| 国产91久久综合| 久久婷婷人人澡人人爽人人爱| 国产精品久久久久久| 久久这里的只有是精品23| 国产精品岛国久久久久| 久久久久国产| 99久久99久久久精品齐齐| 亚洲伊人久久成综合人影院 | 亚洲日本久久久午夜精品| 97久久超碰国产精品2021| 欧美久久一级内射wwwwww.| 久久精品九九亚洲精品| 日本WV一本一道久久香蕉|