• <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>
            posts - 16,  comments - 34,  trackbacks - 0
            共10頁: First 2 3 4 5 6 7 8 9 10 
            re: 對malloc的返回值應該如何轉型 OwnWaterloo 2009-03-17 21:10
            @C++ Beginner
            強制轉換都不會觸發構造函數。

             
            static_cast用于隱式轉換過程,如:
            short s; int i;
            = s; //可以,向更寬整數類型進行隱式轉換。
            = i; //警告,向更窄整數類型轉換。
            = static_cast<short>(i); //過程,明確表明代碼作者的意圖,警告消除。
             
            base* b; derived* d;
            = d; // 可以,向上轉型,隱式轉換。
            = b; // 錯誤,向下轉型,不允許。
            = static_cast<derived*>(b); // 可以,向上轉型的過程。但不保證正確
             
            object* o; void* p;
            = o; // 可以,任何指針類型都可以隱式轉換到void*
            = p; // 過程是錯誤,除非
            = static_cast<object*>(o); // 可以,但不保證正確
             
             
            reinterpret_cast用于整數和指針之間,無繼承關系的指針之間的轉換。
            按照其二進制表示,重新解釋(Re-Interpret),如:
            T* p; intptr_t i;
            = reinterpret_cast<intptr_t>(p);
            // 將p的地址,解釋成一個整數。
            = reinterpret_cast<T*>(i);
            // 將i的值,解釋成一個指向T的指針。
             
            T1* p1; T2* p2;
            p1 
            = reinterpret_cast<T1*>(p2);
            // 將p2中保存的地址的值,復制到p1。
            // 因為p1是T1*類型的指針,以后對p1的操作,將按T1*來解釋

            // 另外一種方式:
            p1 = static_cast<T1*>static_cast<void*>(p2) );
            過段時間把3個“to do”補完了再發你。
            @陳梓瀚(vczh)
            ---------------------------------------------
            如果不兼容的話,怎么調API?所以必須兼容。
            ---------------------------------------------
            ---------------------------------------------
            雖然我也覺得其他編譯器也應該是這樣。
            沒有理由無故的與樓主描述的__cdecl,__stdcall實現不兼容。
            ---------------------------------------------
            我想說的就是這個意思,應該不會有編譯器放棄大多數舊有的C目標文件遵守的約定,另尋它法。


            但是呢。。。 還是不像有個ISO那么有把握。


            http://www.unixwiz.net/techtips/win32-callconv.html
            這篇文章里說了一個入棧順序,和平時所說的右到左不同。
            但在win32上結論是一樣的。

            @陳梓瀚(vczh)
            MSDN就是微軟的編譯器了。

            其他的編譯器是否也是這樣?

            雖然我也覺得其他編譯器也應該是這樣。
            沒有理由無故的與樓主描述的__cdecl,__stdcall實現不兼容。

            但是心里沒譜啊 ……
            樓主作過其他編譯器的調查么?
            有前人作過類似的調查么?
            @陳梓瀚(vczh)
            老兄 你說的是WndPorc吧? WndPorc拿到HWND,然后去查表找this。
            上面說了,這是MFC和wxwidgets處理WndProc的方式。

            對于HOOK,即使通過LPARAM轉型到XXXStruct,拿到一個HWND,也不能保證就有user data。
            比如,程序已經是別人寫好了,根本無法知道他是否有表。
            這時候,就必須HOOK自己想辦法找user data了。
            --------------------------------------------------------------------------------------------
            stdcall、cdecl和fastcall的參數都是從右到左入棧,并且返回值遵循以下規律:
                小于等于4字節結構用EAX
                小于等于8字節結構用EDX:EAX
                浮點數用ST(0)
                其他則在EAX放置一個指針,供返回值使用
            --------------------------------------------------------------------------------------------
             
            請問一下,關于這個規律,是有標準規定的嗎?
            C/C++的書籍或者標準中,都沒有規定調用約定。
            還是說,這些只是事實上的標準?
             
            如果只是事實上的標準,這些規律的應用范圍只限于x86以及其兼容機?


            // plantform.hpp
            typedef char      int8_t;
            // 應該是這樣
            typedef signed char int8_t;



            char可能是signed,也可能是unsigned,由實現決定。

            甚至,char、signed char、unsigned char都是3種不同的類型(無論char是signed還是unsigned)。

            char這里比較特殊……

            QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&mT1));
             
            對這個cast, 可以考慮這么去掉:
             
            LARGE_INTEGER temp = LARGE_INTEGER();
            QueryPerformanceCounter(
            &temp);
            mT1 
            = temp.QuadPart;
            關于高精度數 我有過很多想法 …… 有空討論 ……
            stdint嘛 …… boost里面有。。。
            google 搜搜 也有下載的地方。。。
            你有MinGW就最方便了,直接從MinGW\include下復制就好了
            stdint.h inttypes.h
            都有

            沒必要自己寫吧。。。
            re: 復雜結構體的存取器 OwnWaterloo 2009-02-21 20:07
            @Anonymous
            閣下有何高見? 還是說,只有說屁話的本事?
            re: 如何關閉Visual Studio 2008 OwnWaterloo 2009-02-20 16:43
            試試先用文件菜單里的“關閉解決方案”,等解決方案關掉之后,再關閉VS。
            re: 消息映射機制的簡單實現 OwnWaterloo 2009-02-19 23:23
            @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://m.shnenglu.com/Fox/archive/2008/09/29/63056.aspx#74178
            也說了。

            re: 消息映射機制的簡單實現 OwnWaterloo 2009-02-19 22:42
            @cppexplore

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

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

            re: 消息映射機制的簡單實現 OwnWaterloo 2009-02-19 02:16
            移植性確實會在不支持虛函數的語言中完敗。
            論理解、擴展、維護、簡單的話,你現在仍然覺得虛函數比不上表格嗎?
            re: 消息映射機制的簡單實現 OwnWaterloo 2009-02-19 02:16
                                          考慮擴展
             
            添加一個新的消息處理類。
            如果基類不是純虛函數,那最簡單了,覆寫需要關心的消息就可以了。
            如果是純虛函數,需要實現所有消息處理函數,對不關心的消息,使用基類默認處理。
             
            而你的方案,不得不將所有的消息都映射一遍——因為【消息類型做數組下標,直接定位取處理函數】——即使不關心而作一個空函數。 
            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: 消息映射機制的簡單實現 OwnWaterloo 2009-02-19 01:57
            @cppexplore
            【怎么不直接去我blog回復呢 呵呵】
            好像是cppblog對url的分析有點問題,這個url: http://m.shnenglu.com/CppExplore/archive/2008/11/07/66216.html
            會被截取,只將前面一部分(也就是你的主頁)制作成鏈接,點過去沒看見什么文章……
            后來才發現這個問題,找到那篇文章……
            【容易理解,容易擴展,容易維護,容易移植,容易簡單化】
            嗯,這是重點。同時我也贊同你文章里最后一句話【一句話:重要的是思想,不是平臺和語言?!?br> 
            "你的實現就是模擬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: 消息映射機制的簡單實現 OwnWaterloo 2009-02-18 18:03
            @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: 消息映射機制的簡單實現 OwnWaterloo 2009-02-18 16:40
            @cppexplore

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

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

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

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



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

            re: 消息映射機制的簡單實現 OwnWaterloo 2009-02-18 16:29
            @cppexplore

            1. 時間消耗

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

            2. 空間消耗

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

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


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



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

            你的方案是為了消息路由而消息路由,沒能理解采用消息路由的”苦衷“——如果采用更容易理解的虛函數來實現,虛表將占用比較多的資源,不得已而采用消息路由。
            re: 消息映射機制的簡單實現 OwnWaterloo 2009-02-18 02:30
            @cppexplore
            【消息類型做數組下標了,直接定位取處理函數,這都是無關緊要的細節。】
            這恰恰是最重要的細節 …… 這樣做得不償失……



            re: 從Win32 API封裝Thread類[1] OwnWaterloo 2008-10-10 01:36
            我有2個建議, 一個可以慎重考慮一下, 另外一個可以完全不理睬。
            還有2個疑問 ……

            1.單下劃線開始的標識符?

            2.將windows.h 從thread.h中移走
            .h
            class Thread {
            //
            private:
            uintptr_t handle_;
            }

            .cpp
            handle_ = _beginthreadex 這個可以直接賦值
            CloseHandle( reinterpret_cast<HANDLE>( handle_ ); 這個要自己轉
            雖然麻煩一點, 但是將 windows.h 隔離到了頭文件之外




            疑問:
            1. Thread的析構

            10 Thread::~Thread() {
            11 if (_handle != 0)
            12 CloseHandle(_handle);
            13 if (_target != 0)
            14 delete _target;
            15 }

            CloseHandle 線程并不停止
            如果主線程沒有join delete _target; 后 線程還在run

            這是線程函數
            34 unsigned __stdcall Thread::threadProc(void *param) {
            35 Thread *p = static_cast<Thread*>(param);
            36 if (p->_target != 0)
            37 p->_target->run();
            38 else
            39 p->run();
            40 return 0;
            41 }

            37 行, 如果被delete, 而且run訪問了數據, 而不僅僅是打印一些console消息, 肯定會引發錯誤。


            疑問是: join 是慣例? 規范? 還是僅僅是boost的示例而已。


            2.Thread 似乎并不需要從 Runable 繼承。
            完全可以設計成 Thread是Runable的容器。

            疑問是: 僅僅是為了模仿Java的行為?
            re: 從Win32 API封裝Thread類[1] OwnWaterloo 2008-10-10 01:23
            @Robinfoxnan
            我幫樓主回你了 ~~

            侯捷的書, 肯定說的是不要使用 CreateTread 這個API
            如果他說的是不要使用 _beginthreadex , 那他該被拖出去打。

            至于AfxBeginThread ,windows平臺下寫程序一定要和MFC扯上關系么?

            既然你提到了AfxBeginThread, 你可以去看一下MFC的源碼, MFC80, 它就是使用的 _beginthreadex ~~

            共10頁: First 2 3 4 5 6 7 8 9 10 
            <2025年6月>
            25262728293031
            1234567
            891011121314
            15161718192021
            22232425262728
            293012345

            常用鏈接

            留言簿(8)

            隨筆檔案(16)

            鏈接

            搜索

            •  

            積分與排名

            • 積分 - 198340
            • 排名 - 134

            最新隨筆

            最新評論

            閱讀排行榜

            評論排行榜

            久久中文字幕精品| 少妇久久久久久被弄到高潮 | 久久久无码精品亚洲日韩按摩| 久久综合九色综合97_久久久| 色欲综合久久中文字幕网 | 伊人色综合九久久天天蜜桃| 国产国产成人久久精品| 久久国产视频99电影| 久久精品无码av| 伊人久久国产免费观看视频 | 99久久精品免费国产大片| 好久久免费视频高清| 麻豆精品久久精品色综合| 国产L精品国产亚洲区久久 | 久久午夜电影网| 欧美一区二区精品久久| 国产91久久综合| 亚洲精品tv久久久久| 日韩AV无码久久一区二区| 国产精品美女久久久久网| 大香网伊人久久综合网2020| 亚洲国产精品无码久久九九| 久久婷婷国产剧情内射白浆| 久久精品aⅴ无码中文字字幕重口 久久精品a亚洲国产v高清不卡 | 久久久久久久99精品免费观看| 日本道色综合久久影院| 久久人人爽人人爽人人片AV麻豆 | 国产精品久久久久影院色| 国产精品久久久久影院嫩草| 久久强奷乱码老熟女| 久久精品欧美日韩精品| 青青草原综合久久大伊人导航| 性欧美大战久久久久久久久 | 久久精品国产99国产精品导航| 亚洲精品乱码久久久久久蜜桃图片| 久久99精品久久久久久| 久久天天躁狠狠躁夜夜2020一| 欧美亚洲另类久久综合| 五月丁香综合激情六月久久| 久久成人18免费网站| 国产亚洲美女精品久久久久狼|