• <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>

            cexer

            cexer
            posts - 12, comments - 334, trackbacks - 0, articles - 0
              C++博客 :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理
            共4頁(yè): 1 2 3 4 
            class CTest
            {
            public:
            CTest()
            : m_value( 0x12345678 )
            {
            build_proc();
            }

            public:
            LRESULT CALLBACK member_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
            {
            printf( "hwnd:%d, msg:%d, wparam:%d, lparam:%d\n", (int)hwnd, (int)msg, (int)wparam, (int)lparam );
            printf( "CTest::value: 0x%x\n", m_value );
            return 0;
            }

            void build_proc()
            {
            unsigned char* proc = m_proc;
            ///////////////////////// Prolog.
            __CODE( 1, ( 0x55 ) ); // 55 push ebp
            __CODE( 2, ( 0x8B, 0xEC ) ); // 8B EC mov ebp,esp
            __CODE( 6, ( 0x81, 0xEC, 0xC0, 0x00, 0x00, 0x00 ) ); // 81 EC C0 00 00 00 sub esp,0C0h
            __CODE( 1, ( 0x53 ) ); // 53 push ebx
            __CODE( 1, ( 0x56 ) ); // 56 push esi
            __CODE( 1, ( 0x57 ) ); // 57 push edi
            __CODE( 6, ( 0x8D, 0xBD, 0x40, 0xFF, 0xFF, 0xFF ) ); // 8D BD 40 FF FF FF lea edi,[ebp+FFFFFF40h]
            __CODE( 5, ( 0xB9, 0x30, 0x00, 0x00, 0x00 ) ); // B9 30 00 00 00 mov ecx,30h
            __CODE( 5, ( 0xB8, 0xCC, 0xCC, 0xCC, 0xCC ) ); // B8 CC CC CC CC mov eax,0CCCCCCCCh
            __CODE( 2, ( 0xF3, 0xAB ) ); // F3 AB rep stos dword ptr es:[edi]

            ////////////////////// Codes
            __CODE( 3, ( 0x8B, 0x45, 0x14 ) ); // 8B 45 14 mov eax,dword ptr [ebp+14h] [lparam]
            __CODE( 1, ( 0x50 ) ); // 50 push eax
            __CODE( 3, ( 0x8B, 0x45, 0x10 ) ); // 8B 45 10 mov eax,dword ptr [ebp+10h] [wparam]
            __CODE( 1, ( 0x50 ) ); // 50 push eax
            __CODE( 3, ( 0x8B, 0x55, 0x0C ) ); // 8B 55 0C mov edx,dword ptr [ebp+0Ch] [msg]
            __CODE( 1, ( 0x52 ) ); // 52 push edx
            __CODE( 3, ( 0x8B, 0x45, 0x08 ) ); // 8B 45 08 mov eax,dword ptr [ebp+8] [hwnd]
            __CODE( 1, ( 0x50 ) ); // 50 push eax
            __CODE( 1, ( 0xB9 ) ); __PTR( this ); // B9 ?? ?? ?? ?? mov ecx, this
            __CODE( 1, ( 0x51 ) ); // 51 push ecx
            __CALL( &CTest::member_proc ); // E8 ?? ?? ?? ?? call CTest::member_proc

            /////////////////////// Epilog.
            __CODE( 1, ( 0x5F ) ); // 5F pop edi
            __CODE( 1, ( 0x5E ) ); // 5E pop esi
            __CODE( 1, ( 0x5B ) ); // 5B pop ebx
            __CODE( 6, ( 0x81, 0xC4, 0xC0, 0x00, 0x00, 0x00 ) ); // 81 C4 C0 00 00 00 add esp,0C0h
            __CODE( 2, ( 0x8B, 0xE5 ) ); // 8B E5 mov esp,ebp
            __CODE( 1, ( 0x5D ) ); // 5D pop ebp
            __CODE( 3, ( 0xC2, 0x10, 0x00 ) ); // C2 10 00 ret 10h

            DWORD old = 0;
            VirtualProtect( &m_proc, sizeof(m_proc), PAGE_EXECUTE_READWRITE, &old );
            }

            WNDPROC get_proc()
            {
            return (WNDPROC)(void*)m_proc;
            }

            public:
            char m_proc[1024];
            int m_value;
            };


            int main( int argc, char** argv )
            {
            CTest test;
            WNDPROC proc = test.get_proc();
            proc( (HWND)1, 2, 3, 4 );

            return 0;
            }
            #include <iostream>
            #include <string>
            #include <windows.h>
            #include <cstdio>
            using namespace std;


            template<class T, class S>
            inline T union_cast( S s )
            {
            union
            {
            T t;
            S s;
            } u;
            u.s = s;
            return u.t;
            }

            #define __CODE1( a ) \
            *(proc++) = a

            #define __CODE2( a1, a2 ) \
            *(proc++) = a1; \
            *(proc++) = a2

            #define __CODE3( a1, a2, a3 ) \
            *(proc++) = a1; \
            *(proc++) = a2; \
            *(proc++) = a3

            #define __CODE4( a1, a2, a3, a4 ) \
            *(proc++) = a1; \
            *(proc++) = a2; \
            *(proc++) = a3; \
            *(proc++) = a4

            #define __CODE5( a1, a2, a3, a4, a5 ) \
            *(proc++) = a1; \
            *(proc++) = a2; \
            *(proc++) = a3; \
            *(proc++) = a4; \
            *(proc++) = a5

            #define __CODE6( a1, a2, a3, a4, a5, a6 ) \
            *(proc++) = a1; \
            *(proc++) = a2; \
            *(proc++) = a3; \
            *(proc++) = a4; \
            *(proc++) = a5; \
            *(proc++) = a6

            #define __CODE( n, a ) __CODE##n a

            #define __PTR( p ) \
            { \
            *( (void**)proc ) = union_cast<void*>(p);\
            proc += sizeof(void*); \
            }

            #define __CALL( p ) \
            { \
            *(proc++) = 0xE8; \
            unsigned char* pfunc = union_cast<unsigned char*>(p);\
            *( (ptrdiff_t*)proc ) = pfunc - proc - 4; \
            proc += 4; \
            }
            其實(shí)可以徹底擺脫那個(gè)static,辦法就是在直接(或者使用JITAssembler)手動(dòng)生成static的代碼,跟thunk替換棧上數(shù)據(jù)一樣的道理。只是這樣生成的代碼同時(shí)與編譯器和CPU綁定了,與編譯器綁定是因?yàn)楦鱾€(gè)編譯器生成的調(diào)用成員函數(shù)的方式可能不一樣。
            Android上有很多現(xiàn)成的HTTP服務(wù)端應(yīng)用,另外busybox自帶httpd。不過樓主嘗試一下也不是壞事。
            一樓的同志,好!果然是江湖中人,夠爽快!
            二樓的同事,人家也沒說是賺錢的啊,咋就得了個(gè)”在錯(cuò)誤的道路上越走越遠(yuǎn)“的結(jié)論呢。
            我看挺好的!
            我覺得boost::pool的ordered_malloc和ordered_free函數(shù)是有必要的,它們是作為ordered pool的接口部分而存在的,使用場(chǎng)景不一樣,和malloc和free是沒有可比性。

            boost::pool中有一個(gè)函數(shù)malloc_n用來申請(qǐng)幾塊連續(xù)的partition。一個(gè)block是以partition為粒度劃分,以單向鏈表鏈接起來,多次malloc/free的動(dòng)作之后,這些partition在鏈表中的邏輯順序和它們?cè)趦?nèi)存中的實(shí)際順序極有可能是不一致的,此時(shí)要得到連續(xù)的partition,必須要遍歷鏈表,找出在內(nèi)存中實(shí)際連續(xù)的partition,并將它們?cè)阪湵碇械捻樞蛞仓匦乱赃B續(xù)的順序鏈接,然后返回給調(diào)用者。

            如果將鏈表的順序與內(nèi)存中實(shí)際順序的不一致程度叫做它的無序度,顯然這個(gè)遍歷操作的耗費(fèi)的時(shí)間,和鏈表的無序度是成正比的。如果這種malloc_n的操作很頻繁,那么這種遍歷鏈表重新鏈接的操作會(huì)很費(fèi)時(shí)。

            這種頻繁申請(qǐng)多個(gè)連續(xù)partition的場(chǎng)景下正是使用ordered pool的地方,正如pool作者在代碼寫的注釋那樣:
            // Note: if you're allocating/deallocating n a lot, you should
            // be using an ordered pool.

            ordered pool內(nèi)部的所有partition鏈表無序度為0,即所有partition在內(nèi)存中的實(shí)際順序和它們?cè)阪湵碇械倪壿嬳樞蛲耆恢拢瑢?duì)于malloc_n這樣的請(qǐng)求,可以更快滿足。也因此boost::pool提供了ordered版本的操作接口,這組接口保證每次free之后鏈表的順序不會(huì)亂。

            不過,我個(gè)人覺得block以partition為粒度劃分是沒必要的,可以在收到請(qǐng)求的時(shí)候按實(shí)際需求劃分,盡力使整個(gè)塊保持連續(xù),可以極大地避免產(chǎn)生碎片,降低ordered_malloc的ordered_free的時(shí)間。

            當(dāng)然ordered_xxx函數(shù)不應(yīng)該和其它的函數(shù)混用,否則就是陪了夫人又折兵的買賣,即浪費(fèi)了ordered_xxx的時(shí)間,又無法得到更快malloc_n的好處。
            當(dāng)使用CreateProcess傳入命令行參數(shù)的時(shí)候,argv[0]可以是任何值,不一定是程序路徑或程序名。
            搞笑啊,樓上你冒用ID很光彩?看來被人罵傻逼沒罵錯(cuò)
            那些出口就罵人的,都是些畜牲嗎?你爹媽沒教過你怎么說人話?
            樓主你的文章質(zhì)量都不錯(cuò),就是有點(diǎn)偏離群眾口味。
            嵌入式?如果是一般應(yīng)用開發(fā)面試出這種題有點(diǎn)不靠譜,寫產(chǎn)品的人哪能鉆到這樣的細(xì)節(jié)里去。
            @三夏健
            說得有道理,并且我補(bǔ)充你一下,“紙上得來終覺淺,絕知此事要躬行”,這句話不能太單純地理解。首先第一步要“紙上得來”,如果自己的理解已經(jīng)超越了紙面上能給你的,然后就再“躬行”。理論基礎(chǔ)要扎實(shí),實(shí)踐才能有的放矢。另外有些東西是知識(shí)結(jié)構(gòu)的基本結(jié)點(diǎn),比如說“1+1=2”,本來就是“淺”的,沒必要“躬行”。
            re: C++雜談[未登錄] cexer 2011-07-14 20:45
            應(yīng)用的框架到了比較高的階段,所面臨的問題的寬度和深度已經(jīng)完全超越了語言之間的微妙界線,所以像 shared_ptr 這類語言底層的東西,不能拿到這種場(chǎng)合來說。boost 是個(gè)大雜噲,有些東西用起來很不錯(cuò),比如說 shared_ptr,有些東西不是拿來用的,是實(shí)驗(yàn)室產(chǎn)物,像你說的 tuple 確實(shí)是不大實(shí)用。
            上面有人竟然拿 auto_ptr 來說多 CPU 并發(fā)。這種問題就好像,你在路上撿到一塊鼠標(biāo)墊,然后就開始發(fā)愁,還配點(diǎn)啥才能玩上魔獸世界。
            re: c++處女類[未登錄] cexer 2011-07-14 20:30
            大哥,C++是語言的藝術(shù),講究說學(xué)逗唱,你直接擺代碼是怎么個(gè)回事啊。
            這跟在沒在首頁(yè)可沒關(guān)系。我是說解決問題的方式,像導(dǎo)出符號(hào)這種按步就搬的套路,自己去猜,從學(xué)習(xí)成長(zhǎng)的角度來說,不如系統(tǒng)地找本書看看來得有效率。雖然自己試,長(zhǎng)久下來也能積累知識(shí),只是學(xué)習(xí)到了一個(gè)階段就會(huì)有瓶頸,需要把零散知識(shí)融匯貫通的時(shí)候就不如那么隨心所欲了,會(huì)有那種怎么也打不通仁督二脈的感覺。另外,我是以為以為樓主寫了一個(gè)類似 dll2lib 的工具,就點(diǎn)進(jìn)來的,有點(diǎn)上當(dāng)?shù)母杏X啊。
            知識(shí)結(jié)構(gòu)得系統(tǒng),完整,別自己東弄一點(diǎn)西猜一點(diǎn),零零散散散的,自己不懂就找個(gè)教程找本書從頭至尾好好看看,要不出了問題都不知道在哪里.
            不管是不是牛人,與人討論的時(shí)候,都不要擺出“蹉,來食”的施舍姿態(tài)。作為做技術(shù)的,術(shù)業(yè)有專攻,沒有誰是十項(xiàng)全能宇宙無敵的,所以不要輕易否定別人的成果。作為做人的基本原則,行前三思言必三省,考慮一下自己的言行是否會(huì)破壞別人的心情。

            模式匹配我了解的不多,不過詞法分析正則表達(dá)式有窮自動(dòng)機(jī)什么的,是成熟很多年的技術(shù)了,只是能沉下心來啃書寫代碼的人不多,能有自己思考的人更少,因此我很佩服樓主的編譯器功底。《代碼之美》看過,與想像中的有差距,比較雞肋的一本書,樓主所說的代碼剛好也看過,飯同學(xué)的代碼確實(shí)不如它精巧,但是貴在原創(chuàng),我能夠體會(huì)他的成就感被人擊破時(shí)的氣憤。

            既然飯同學(xué)說你態(tài)度有問題,你就有則改之,無則加勉好了。如果有一個(gè)人說你有問題,你可以不必太在意。如果有兩個(gè)人說你有問題,你就要想想到底是誰的問題了。如果有三個(gè)人說你有問題,那就是你一定有問題了。


            不錯(cuò)的文章,樓主是個(gè)低調(diào)做事的人,支持!
            我拜托把這難看的界面改改,回復(fù)功能增強(qiáng)一點(diǎn)。
            實(shí)現(xiàn)一個(gè)functor,除了眾所周知的功能,我建議樓主再考慮以下這兩點(diǎn):

            1 給返回void(無返回值)的functor綁定一個(gè)有返回值的可調(diào)用體,這個(gè)貌似boost::function是支持的。這功能是需要的,因?yàn)閷?shí)際上很多時(shí)候,我們的functor不關(guān)心返回值,就好像某個(gè)消息無論你返回什么系統(tǒng)都執(zhí)行相同的操作,這種情況下,如果綁定的可調(diào)用體返回了什么值,functor應(yīng)該檢測(cè)到并使用某種屏蔽手段,而不是報(bào)錯(cuò)“對(duì)不起,返回類似不匹配”。

            2 給返回非void(有返回值)的functor綁定一個(gè)返回void(無返回值)的可調(diào)用體,這個(gè)貌似boost::function不支持。這功能是需要的,因?yàn)橛袝r(shí)候functor需要一個(gè)明確的返回值,就像WM_ERASEBKGND消息,根據(jù)返回TRUE或FALSE的不同,系統(tǒng)會(huì)決定是否自己來畫窗口背景。如果可調(diào)用體返回void(無返回值),那么functor應(yīng)該檢測(cè)到它,并在返回時(shí)提供一個(gè)默認(rèn)的返回值,而不是在綁定時(shí)就報(bào)錯(cuò)“對(duì)不起,返回類似不匹配”。

            以上兩點(diǎn)都可以通過模板元編程實(shí)現(xiàn),通過typetraits檢測(cè)返回值,并根據(jù)functor和可調(diào)用體之兩者返回值的不同組合,來選擇不同的返回策略。

            另外還有,如果想綁定系統(tǒng)函數(shù)如Windows API,或者其它第三方提供的函數(shù),你還需要考慮調(diào)用約定的問題,因?yàn)?__stdcall,__cdecl,__fastcall的不同,都會(huì)使函數(shù)簽名不同。有多少種調(diào)用約定,functor的綁定函數(shù)的數(shù)量就需要乘以多少,這是個(gè)體力活,可以用預(yù)處理元和文件包含來減少體力消耗。
            @飛舞的煙灰缸
            【function的多播實(shí)現(xiàn)還是有點(diǎn)麻煩。
            += 倒是簡(jiǎn)單,但是要實(shí)現(xiàn) -=這樣的操作就需要判斷function相等,麻煩就比較大了】

            我想你指的麻煩,可能是你想實(shí)現(xiàn)這樣的功能:
            // 加入
            on_event += message_handler( handler );
            // 刪除
            on_event -= message_handler( handler );

            // 加入
            on_event += message_handler ( &Window::handle_resized,this );
            // 刪除
            on_event -= message_handler ( &Window::handle_resized,this );

            這樣的方式實(shí)現(xiàn)其實(shí)也不難,但是絕對(duì)需要 RTTI 那種東西的支持,另外還有一個(gè)問題就是這樣的方式使用用起來太麻煩,比如:

            // 加入
            on_event += message_handler ( &Window::handle_resized,this );
            // 刪除
            on_event -= message_handler ( &Window::handle_resized,this );

            如果庫(kù)提供了類似 boost::asio 那種參數(shù)綁定的功能,看看有多麻煩:
            // 加入
            on_event += message_handler ( &Window::handle_resized,this,Argument::size,Argument::caption );
            // 刪除
            on_event -= message_handler ( &Window::handle_resized,this,Argument::size,Argument::caption );


            其實(shí)這個(gè)功能有比你個(gè)簡(jiǎn)單得多的實(shí)現(xiàn)方式,給一個(gè) handler 綁定一個(gè)名字,到時(shí)刪除這個(gè)名字即可,見下例:
            // 加入
            on_event += message_handler ( name,handler );
            // 刪除
            on_event -= message_handler( name );


            @OwnWaterloo
            【借寶地請(qǐng)教一下~ 對(duì)于handler, 是否需要如此的動(dòng)態(tài)?
            A. 完全動(dòng)態(tài)
            B. 完全靜態(tài)
            C. 兩者結(jié)合, 動(dòng)態(tài)部分自己實(shí)現(xiàn)。
            如上, 需要A那種靈活性么? 缺之不可?
            因?yàn)槲易约捍_實(shí)沒寫過幾個(gè)gui程序, "作為一個(gè)庫(kù)的用戶", 沒有足夠的這方面的使用經(jīng)驗(yàn)。】


            說說我的看法:A并不是必須的,比如說MFC,可以算是完全靜態(tài)的,其所有的消息映射代碼都是用宏堆死的選擇語句,提供的動(dòng)態(tài)功能基本上無,優(yōu)勢(shì)很明顯,一個(gè)類的所有實(shí)例共享一份映射數(shù)據(jù),具有空間優(yōu)勢(shì)。但是一個(gè)獨(dú)立的對(duì)象不能有它自己處理事件的方式,這明顯不是面向?qū)ο蟮姆庋b方式,運(yùn)行時(shí)靈活性大打折扣,這樣說起來很模糊,仍然舉例MFC來說明:

            比如說使用MFC運(yùn)行時(shí)創(chuàng)建的一個(gè)按鈕,怎么樣才能把這個(gè)按鈕的消息加到消息映射里去呢?對(duì)不起,不能。因?yàn)榘粹oID是動(dòng)態(tài)生成的,那些映射宏什么的到運(yùn)行時(shí)都成了浮云。解決辦法當(dāng)然也有:回到原始時(shí)代--要么在父窗口的消息回調(diào)函數(shù)里檢查WM_COMMAND和BN_CLICK,二是任勞任怨地去自己重寫一個(gè)按鈕類,并在自己的消息回調(diào)里響應(yīng)WM_COMMAND的反射消息并檢測(cè)BN_CLICK,然后進(jìn)行處理--看看有多麻煩。

            所以我覺得一個(gè)好的庫(kù),應(yīng)該能夠同時(shí)提供兩者,就是你說的C。同時(shí)支持靜態(tài)和動(dòng)態(tài)的映射方式,關(guān)鍵是庫(kù)要實(shí)現(xiàn)得好,在沒有使用動(dòng)態(tài)映射的時(shí)候,這個(gè)動(dòng)態(tài)映射的功能就好像不存在一樣,這樣大多數(shù)時(shí)候既能夠享受空間優(yōu)勢(shì),在需要的時(shí)候又能發(fā)揮它的動(dòng)態(tài)優(yōu)勢(shì)。免得用戶要在在空間優(yōu)勢(shì)和靈活性之間做出痛苦的選擇。
            不說MFC那種陳舊的消息機(jī)制,用boost::function,boost::bind,boost::signal之類的來實(shí)現(xiàn)消息機(jī)制,也算有點(diǎn)out了,而且這種實(shí)現(xiàn)已經(jīng)有框架使用(比如SmartWin++),不再具有新意了,其實(shí)強(qiáng)大的C++可以完成遠(yuǎn)比它們更高級(jí)的功能,列舉三點(diǎn):

            1 框架可以給同一個(gè)消息源添加任意多個(gè)個(gè)完全不同的消息處理器,類似函數(shù)重載,可以將這個(gè)功能命名為處理器重載。僅僅是類似boost:function和boost:signal那種固定簽名的工具,是無法完成這樣的功能的,如下所示:

            // 自由函數(shù)
            void global_handler(){}

            // 一段腳本
            Script script_handler = create_script( /*這是一段腳本*/ );

            // 系統(tǒng)函數(shù)
            int WINAPI MessageBox( HWND,LPCTSTR,LPCTSTR,UINT );

            // 具有不同參數(shù)的成員函數(shù)
            viod Class:memeber_handler_void(){}
            void Class::member_handler_size( Size size ){}
            void Class::member_handler_int( int x,int y ){}

            // 消息映射
            Window window;
            Class object;
            window.on_resized += message_handler( global_handler );
            window.on_resized += message_handler( script_handler );
            window.on_resized += message_handler( &Class::member_handler_void,&object );
            window.on_resized += message_handler( &Class::member_handler_size,&object );
            window.on_resized += message_handler( &Class::member_handler_int ,&object );
            window.on_resized += message_handler( &::MessageBox,NULL,"Hello World",MB_OK );


            2 框架能夠進(jìn)行返回值檢查(眾所周知的,在windows消息系統(tǒng)中,很多消息需要進(jìn)行特殊的返回值檢查,強(qiáng)WM_ERASEBKGND之類的),比如一個(gè)closing消息,如果處理器返回非void類型,并且能夠強(qiáng)制轉(zhuǎn)換為true,則表明它同意關(guān)閉窗口,如果能夠強(qiáng)制轉(zhuǎn)換為false,則表示它阻止框架進(jìn)行關(guān)閉,如果處理器返回值類型是void,則表示它不關(guān)心關(guān)閉與否,讓框架進(jìn)行默認(rèn)處理。這個(gè)功能可以命名為返回值智能檢測(cè)。如下所示:

            // 這個(gè)處理器不關(guān)心窗口是否要關(guān)閉
            void handle_closing_dont_care( Window* window )
            {
            }

            // 這個(gè)處理器告訴框架不要關(guān)閉
            LRESULT handle_closing_no()
            {
            return 0;
            }

            // 這個(gè)處理器告訴框架進(jìn)行關(guān)閉
            bool handle_closing_yes()
            {
            return true;
            }

            // 消息映射,窗口最終是否關(guān)閉取決于最后一個(gè)處理器的決定。
            Window window
            window.on_closing += message_handler( handle_closing_dont_care );
            window.on_closing += message_handler( handle_closing_no );
            window.on_closing += message_handler( handle_closing_yes );


            3 框架提供消息分解者,允許使用者自己組合自己的處理器參數(shù),類似boost::asio的handler綁定bytes_transfered和error_code的方式,可以把這個(gè)功能命名為消息參數(shù)任意組合,比如同一個(gè)消息resized,有的處理器需要當(dāng)前窗口的大小,有的處理器需要當(dāng)前窗口的標(biāo)題,有的處理器同時(shí)需要兩者,則消息映射時(shí)手動(dòng)組合消息分解者即可。更進(jìn)一步,對(duì)于某些預(yù)注冊(cè)的簽名,框架可以智能提供分解者,免去使用者手動(dòng)提供的麻煩,例如簽名 (Window*,Size) 已經(jīng)預(yù)先注冊(cè),則具有這個(gè)簽名的處理器不用手動(dòng)指定消息分解器
            示例代碼如下:

            // 這個(gè)處理器需要當(dāng)前窗口大小
            void handle_resized_size( Size size ){}

            // 這個(gè)處理器需要窗口標(biāo)題
            void handle_resized_text( String caption ){}

            // 這個(gè)處理器都需要
            void handle_resized_both( Size size,String caption )


            // 消息映射的時(shí)候,同時(shí)指示自己需要什么參數(shù)
            Window window
            window.on_resized += message_handler( handle_resized_size,Window::Argument::size )
            window.on_resized += message_handler( handle_resized_text,Window::Argument::text )
            window.on_resized += message_handler( handle_resized_both,Window::Argument::size,Window::Argument::text )


            void handle_resized( Window* window,Size size ){}
            window.on_resized += message_handler( handle_resized );

            4 但是。。。。。在C++.0x.lamda的面前,以上一切都成了浮云。把lamda作為消息處理器,它自身就同時(shí)提供了以上1,2,3的所有優(yōu)點(diǎn),簡(jiǎn)潔優(yōu)雅使用方便,物美價(jià)廉童叟無欺,以上例說明:

            // 這個(gè)處理器需要當(dāng)前窗口大小
            window.on_resized += []( Size size ){
            }( window::Argument::size );

            // 這個(gè)處理器需要窗口標(biāo)題
            window.on_resized += []( String caption ){
            }( Window::Argument::text );

            // 這個(gè)處理器都需要
            window.on_resized += []( Size size,String caption ){
            }( window::Argument::size,Window::Argument::text );

            我正在寫的就是這么一個(gè)框架,上面列舉的消息機(jī)制都完成了,正在進(jìn)行博主所指第4步封裝控件和第5步(寫文檔,作為一個(gè)目標(biāo)是開源的框架,是最重要的步驟),目前代碼已經(jīng)有兩萬多行,消息機(jī)制的其實(shí)占很少部分,大多代碼是控件的封裝。

            re: 軟件開源很重要嗎? cexer 2010-09-21 22:24
            我覺得軟件開源沒有合不合適和值不值得,只有愿不愿意。同時(shí),不管開源如何地重要,開源與否都只是一種權(quán)利,不是義務(wù),除非誰寫的代碼已經(jīng)牛到了使人類科技跳躍發(fā)展二十年的程度,他不開源人類就要被外星人消滅。

            但是真正要問一下,軟件開源重要嗎?我想沒人會(huì)給出否定的答案。如果沒有開源這東西,很難想像如今的軟件行業(yè)還在哪個(gè)歷史階段以蝸速前進(jìn)。所以作為程序員,在保證自己利益的前提下進(jìn)行開源,于人于已都是最好的。蜘蛛俠里有句話:“有多大的能力,就承擔(dān)多大的責(zé)任”。

            話又說回來,那些不能滿足自己欲望就攻擊別人的人,有不如人的,有得不到的,就吐口水翻白眼罵臟話的人,和低等級(jí)動(dòng)物沒有區(qū)別。對(duì)于這類缺乏基本教養(yǎng)的動(dòng)物,它叫得越厲害越反而不要給它,就讓它在那里出丑。要不然你給它了它會(huì)嫌你的東西不好,罵得更厲害。

            網(wǎng)絡(luò)是個(gè)大黑屋,沒有道德和法律的探照燈,反而可以顯出人和人的區(qū)別。按理說技術(shù)社區(qū)既沒有政治立場(chǎng)的對(duì)立,也沒有經(jīng)濟(jì)利益的沖突,純粹的技術(shù)交流應(yīng)該是很愉快的,去過一些國(guó)外的技術(shù)社區(qū)也基本上氣氛就是這樣單純。但是神奇的中國(guó),就連技術(shù)社區(qū)都那么地不和諧,所以說垃圾已經(jīng)塞滿中國(guó)社會(huì)各個(gè)角落。

            @陳梓瀚(vczh)
            我對(duì)這個(gè)主題相關(guān)的技術(shù)不感興趣。之所以留言,是覺得這篇日志的標(biāo)題不妥,標(biāo)題說“如何設(shè)計(jì)世界上最好的”,內(nèi)容里卻只“舉出一些需要注意的地方”,既沒見“設(shè)計(jì)”,更不知“如何”,幾張圖倒是占了大部分的篇幅,這樣的話,“我寫過的一個(gè)代碼行統(tǒng)計(jì)工具”是個(gè)更適合的標(biāo)題。
            沒有看到你對(duì)題目中《如何....》的解答,只看到提出問題,沒有看到提供解決方案。
            確實(shí)好電影,好久沒看過這么好看的電影了。不過呢,還是有些不足,雪地槍戰(zhàn)戲雖然有了架子,可是節(jié)奏單調(diào)沒有高潮,失重狀態(tài)的打斗也沒有打擊感,隔靴騷癢一樣,我覺得這兩個(gè)地方可以更精彩。配樂單薄,電影過后完全沒有配樂的回味,應(yīng)該找 Hans Zimmer 來配樂(竟然還真是他配的)。

            很喜歡電影的結(jié)尾。最后從最底層夢(mèng)中醒來的過程,導(dǎo)演故意處理沒有過渡,直接簡(jiǎn)單得讓人難以相信。醒來后的一切又是那么朦朧,周圍人的眼神,兩個(gè)孩子的穿著和動(dòng)作,留給觀眾一個(gè)大懸念:陀螺到底會(huì)不會(huì)停下來?
            很多人先有罵人的欲望,再找罵人的理由,所謂欲罵之人,何患無罪,跟幾流學(xué)校什么的無關(guān)。樓主不必和這類人一般見識(shí),有一句話說得好,不要和SB講道理,因?yàn)樗麜?huì)把你的智商拉到和他同一水平,然后以多年的SB經(jīng)驗(yàn)打敗你。

            最近老聽說起造輪子。看看開發(fā)技術(shù)的發(fā)展史,只有造輪子才是技術(shù)發(fā)展的唯一道路。只是中國(guó)造輪子的人雖多,可是造大輪子的人太少,小打小鬧的功能類太多,能大規(guī)模復(fù)用的框架太少。至于那些批判造輪子的人,忍受了東拼西湊,偷這抄那的道德譴責(zé),忍受了接口參差,代碼混亂的身心煎熬,最終能夠完成項(xiàng)目,雖然也是一種勇氣,但不知道他們批判別人的優(yōu)越感來自哪里。

            關(guān)于首頁(yè)原創(chuàng)創(chuàng)精華。CPPBLOG是一個(gè)不知進(jìn)取的博客園,n年了界面和功能從未有一點(diǎn)的進(jìn)步,界面難看不說了,作為一個(gè)技術(shù)社區(qū),連首頁(yè)推薦模塊都沒有,回復(fù)功能之弱讓vckbase驚嘆,使CSDN側(cè)目,所謂首頁(yè)的原創(chuàng)精華,有無私的分享,也有自大的炫耀,有原創(chuàng)的思考,也有盲目的轉(zhuǎn)載,隨便什么人寫了兩行腳本,完成了一個(gè)家庭作業(yè),都可以放到首頁(yè)原創(chuàng)精華區(qū)去,整個(gè)博客園無管理無組織,也讓人沒有寫東西的欲望。

            @白云哥

            [[[[“Because vectors keep an array format, erasing on positions other than the vector end also moves all the elements after the segment erased to their new positions”

            “This invalidates all iterator and references to elements after position or first.”

            刪除對(duì)象后會(huì)讓迭代器之后的對(duì)象移動(dòng),因此而導(dǎo)致迭代器失效


            map的實(shí)現(xiàn),紅黑樹,在插入和刪除對(duì)象后因?yàn)橐銎胶猓酝瑯右灿锌赡軐?dǎo)致迭代器的失效]]]]

            就這兩條原因,不會(huì)使迭代器失效,我所說的迭代器失效,是指容納它數(shù)據(jù)結(jié)構(gòu)的內(nèi)存不存在。對(duì)于連續(xù)內(nèi)存的容器,刪除進(jìn)行元素移位,迭代器的內(nèi)存還在,對(duì)于非連續(xù)內(nèi)存的操作,map,list,set之類的都鏈?zhǔn)降膶?shí)現(xiàn),這類的結(jié)點(diǎn)銷毀的應(yīng)該只是鏈當(dāng)前結(jié)點(diǎn),對(duì)其它結(jié)點(diǎn)的只有修改,所以不應(yīng)該失效。至于2010為什么失效,有點(diǎn)好奇,刪除操作也要內(nèi)存重分配,我覺得這是不好的實(shí)現(xiàn)。
            可以結(jié)合兩種方法。刪除用標(biāo)記緩存刪除的方法,添加用緩存延遲添加的方法好。
            @白云哥
            呵呵,學(xué)習(xí)了,看來還是你的辦法穩(wěn)當(dāng)。這確實(shí)是標(biāo)準(zhǔn)庫(kù)的實(shí)現(xiàn)相關(guān)的,我上面說的也都是基于估計(jì)它的一般實(shí)現(xiàn),很好奇2010的vector是怎么樣實(shí)現(xiàn)的,會(huì)出現(xiàn)這種失效的問題。
            @白云哥
            你看到只刪除了一半,是因?yàn)閷?duì)于vector這種容器,移除前面元素,后面的元素會(huì)整體往移一位,本來指向下一個(gè)元素的迭代器指向了下下個(gè)元素,后面的循環(huán)會(huì)漏掉下一個(gè)元素,這個(gè)我在上面也說過的。對(duì)于list,set,map之類的就能完全刪除。需要從中間刪除的容器,最好不要用vector,元素移位的操作不是常數(shù)時(shí)間的。
            @白云哥
            容器循環(huán)中的操作有四種,循環(huán)中查詢,循環(huán)中更改,循環(huán)中刪除,循環(huán)中添加,這些操作都圍繞迭代器進(jìn)行的。
            循環(huán)中查詢,循環(huán)中更改(這兩類操作其實(shí)也包含了循環(huán)中循環(huán),循環(huán)中的循環(huán)中的循環(huán),循環(huán)中的循環(huán)中的循環(huán)中的循環(huán)。。。)因?yàn)椴粫?huì)改變迭代器的合法性,不會(huì)有什么問題。

            循環(huán)中添加和刪除則不一樣,循環(huán)中添加有可能導(dǎo)致所有元素內(nèi)存重分配,導(dǎo)致所有迭代器失效,而刪除操作一般來說不會(huì)產(chǎn)生內(nèi)存重分配的情況,目前std內(nèi)的容器應(yīng)該都是如此(七分分析三分猜測(cè),正確性八九不離十)。

            所以循環(huán)中刪除只會(huì)使當(dāng)前刪除操作的迭代器失效,使得不能更新之使其指向下一個(gè)元素,而不會(huì)影其它迭代器。如list這類的容器,所有元素內(nèi)存都是單獨(dú)分配的,針對(duì)添加操作進(jìn)行一次單獨(dú)的內(nèi)存分配,不會(huì)影響到現(xiàn)在有迭代器的合法性 ,但有可能刪除操作導(dǎo)致元素重排,元素移位,使得循環(huán)不完全,漏掉元素。

            循環(huán)中添加如果導(dǎo)致內(nèi)存重分配,則會(huì)使所有現(xiàn)有的迭代器失效,例如vector,string這類容器要保證其內(nèi)存是連續(xù)的,添加時(shí)內(nèi)存有可能會(huì)重分配,導(dǎo)致以前的迭代器全部失效。

            所以針對(duì)循環(huán)中添加和刪除的幾種解決方法分析如下:
            在循環(huán)中保存下一個(gè)迭代器的方法:對(duì)于刪除操作是沒有任何問題的(關(guān)于你說的“刪除容器對(duì)象有可能使得之前所保存的迭代器全都失效”,目前std內(nèi)的容器應(yīng)該都不會(huì)發(fā)生這種情況),但對(duì)于添加操作,則只適用于非連續(xù)內(nèi)存的容器如list,不適用于連續(xù)內(nèi)存的容器如vector。這個(gè)辦法優(yōu)點(diǎn)是沒有時(shí)間空間的成本,缺點(diǎn)是對(duì)于添加操作,有些容器不支持。

            使用緩存進(jìn)行延遲操作的方法:對(duì)于刪除和添加都適用,只是需要在所有接口中小心管理m_is_looping,避免重入的問題。優(yōu)點(diǎn)是添加和刪除都適用,缺點(diǎn)是空間時(shí)間的效率損失最大。

            使用刪除標(biāo)志延遲刪除的方法:對(duì)于刪除操作適用,也不存在其它地方刪除會(huì)出問題的情況,因?yàn)檫@個(gè)方法實(shí)際上是把循環(huán)中刪除的操作轉(zhuǎn)化為一個(gè)循環(huán)中更改的操作,所有迭代器都不會(huì)失效。即使刪除操作會(huì)導(dǎo)致容器內(nèi)存重分配,這個(gè)辦法也可行,這是其優(yōu)點(diǎn),缺點(diǎn)是不能用于循環(huán)中添加的操作。
            博主弄復(fù)雜了,這種方法是治標(biāo)不治本的,如果容器中裝的是拷貝刪成本很大的東西,這樣效率就低了。循環(huán)中刪的問題在于刪除操作之后,當(dāng)前迭代器已經(jīng)失效,因此無法更新之使其指向容器中的下一個(gè)元素。強(qiáng)行對(duì)迭代器進(jìn)行 ++ 操作更新,會(huì)出現(xiàn)訪問異常。所以只要?jiǎng)h除之前,用一個(gè)額外的迭代器記住下一個(gè)元素的位置就行了。
            如下:
            //////////////////////////////////////////

            iterator it_this = containter.begin();
            iterator it_next;
            while ( it_this != container.end() )
            {
                it_next = it_this; // 之所以不直接使用 it_next=it_this+1
                ++ it_next;      // 是因?yàn)橛行┤萜鞑恢С蛛S機(jī)訪問,其迭代器不能直接 + n
                do_remove( it_this );
                it_this = it_next;
            }

            /////////////////////////////////////////////////////

            樓上的“僵尸狀態(tài)”也是一個(gè)辦法,不過正如它的名字一樣的,“僵尸”是個(gè)惡心的存在。程序在某一次循環(huán)中,把一堆元素標(biāo)記為僵尸,這一堆東西必須要等到下一次循環(huán)檢查才能清理掉,如果沒有專門的定時(shí)清理機(jī)制,這個(gè)下一次有可能十分之一柱香之后,也有可能是一萬年,甚至有可能程序流程再也沒有這樣的下一次。在被清理掉之前那一堆僵尸在容器里腐爛發(fā)臭,占用空間內(nèi)存,可能直到最后容器銷毀。可以增加專門定時(shí)清理機(jī)制,但是復(fù)雜度和成本又得另外計(jì)算。所以最好的辦法還是就地處決,并且毀尸滅跡。


            見過的最強(qiáng)的的布局管理器是WOW的。布局管理器一般實(shí)現(xiàn)得都靈活性不高,使用起來的代碼不比手寫MoveWindow少多少,能實(shí)現(xiàn)的布局也太有限。寫的好的像WOW那種的確實(shí)很強(qiáng)大,不過實(shí)現(xiàn)起來太費(fèi)精力了,使用起來也不如MoveWindow直觀,反正我自己寫GUI框架是不寫這個(gè)的。
            這種人哪里都有的,樓主息怒。
            @OwnWaterloo
            我說的可能不大清楚,我的意思是“單件模式”只是一種概念,正是類似“全局?jǐn)?shù)據(jù)”這種東西的一種抽象形容,不然何以稱“模式”。拿“單件模式”和“全局?jǐn)?shù)據(jù)”本身比,是沒有可比性的,一為抽象,一個(gè)具體,一為模式,一為實(shí)例。它跟OO也沒有關(guān)系,一個(gè)C全局裸指針,也是一份單件的實(shí)體。所以不要再比來比去的了。

            把單件放在其它模式堆里,確實(shí)有點(diǎn)雞立鶴群的感覺,它并沒有其它模式那樣有啟發(fā)性,所有寫程序的人都知道世上有全局變量這個(gè)東西,那何必要取個(gè)好聽的名字像模像樣地研究一番呢,《設(shè)計(jì)模式》的偉大除了讓人學(xué)會(huì)到很多手法,還有一點(diǎn)就是統(tǒng)一了很多概念,并為之提供了許多標(biāo)準(zhǔn)的名詞方便大家研究,綜上所述,我覺得“單件”就是一個(gè)虛名,你喜歡叫它“全局變量”也行,大家心里的概念沒有差別,只是未必真是用全局變量來實(shí)現(xiàn)而已,所以不用在一個(gè)名字上糾結(jié)。

            誰不想用赤祼祼的全局指針,它們?cè)加旨儤悖烊粺o雕飾。可是真的要用它們來實(shí)現(xiàn)一份庫(kù)級(jí)別的代碼,就好像雙手拋飛刀一樣危險(xiǎn),不僅拋的人要兩眼圓睜神經(jīng)緊繃,連觀眾都要跟著捏一把冷汗。全局變量本來沒有錯(cuò),錯(cuò)的是在它們之上作出的許多美好的假設(shè),假設(shè)誰一定在誰之前產(chǎn)生,誰一定在誰之后銷毀,誰依賴著誰,誰又被誰依賴著,誰是線程安全的,誰又一定不會(huì)被多線程訪問。互相完全沒有依賴關(guān)系,不用額外控制,像終結(jié)者一樣智能,完成任務(wù)又知道自己終結(jié)的全局變量,只是個(gè)傳說。

            有很多以單件名字的手法,Meyers 單件,Alexandrescu 單件,Phoenix 單件,Schwarz 計(jì)數(shù)器,你看它們好多都叫做“單件”,但是你喜歡叫 Meyers 全局對(duì)象,Alexandrescu 全局對(duì)象,Phoenix 全局對(duì)象 也可以。

            我個(gè)人覺得,把“全局變量”拿來和“單件”相提并論是很不妥的事件。就好像拿“汽車”和“交通工具”比一樣。不是一個(gè)層面上的東西,單件也許是全局變量,也可以不是,“全局”也有多種理解角度,存儲(chǔ)位置(堆上,棧上,靜態(tài)數(shù)據(jù)區(qū)),生存區(qū)域(線程局部,進(jìn)程局部,模塊內(nèi)部),生存周期(何時(shí)生,何時(shí)死,不死)。只是“全局變量”已經(jīng)不能說明它的復(fù)雜度,但是一提“單件”大家都明白將要說的是什么,這就是“單件”存在的價(jià)值,這也是《設(shè)計(jì)模式》一書提出“單件模式”偉大所在。
            re: GUI框架:消息檢查者 cexer 2009-12-01 10:10
            @lch
            這個(gè)我同意。不過到后來的豐富控件,已經(jīng)基本上是體力活了。

            re: GUI框架:消息檢查者 cexer 2009-11-26 17:28
            @lch
            一個(gè)是手段,一個(gè)是目的,何來重要和更重要之說。
            re: ffmpeg小試 cexer 2009-11-24 17:47
            最近開始研究 ffmpeg,關(guān)注一下博主。
            re: GUI框架:消息檢查者 cexer 2009-11-24 10:38
            【你那個(gè)MessageChecker怎么完成以一己之身完成,眾多不同功能的?
            同樣可以應(yīng)用到message_checker 上,兩者是相通的,都是靠結(jié)構(gòu)體中嵌的一個(gè)函數(shù)指針。】
            我的意思是函數(shù)本身不容易實(shí)現(xiàn),只用函數(shù)主要有數(shù)據(jù)保存的問題。加上 function 來實(shí)現(xiàn)就容易了,直接綁定一些檢查函數(shù)和檢查的數(shù)據(jù):
                typedef boost::function<bool (const Message&)> MessageChecker

                bool checkCommand( const Message& message,WORD id,WORD code );
                MessageChecker checkYesClicked = boost::bind( &checkCommand,_1,IDYES,BN_CLICKED );

                bool checkMessage( const Message& message,UINT messageId, );
                MessageChecker checkCreated = boost::bind( &checkMessage,_1,WM_CREATE );

            【其實(shí)我是被這段語法吸引的:
                window.onCreated += messageHandler( &::_handleCreated );
                window.onCreated += messageHandler ( this,&Window::_handleCreated );
            很像boost.signal。
            而且真正吸引人的是樓主說它是廉價(jià)工人~_~】
            += 之前的和之后的是兩個(gè)不同的東西,onCreated 是幫助消息映射的一個(gè)東西,其實(shí)就是一個(gè)轉(zhuǎn)發(fā)調(diào)用,所以成本很低。messageHandler() 是消息處理者和消息分解者共同組成的東西。在這里 ::_handleCreated 和 Window::_handleCreated 參數(shù)列表可以是不同的,這里和 boost.signal 不大一樣,因?yàn)橐粋€(gè) signal 只能對(duì)應(yīng)一種 signautre 的 functor 的。

            【boost.function如果不用支持bind,可能可以不動(dòng)用動(dòng)態(tài)存儲(chǔ)。
            要支持bind…… 而且不使用動(dòng)態(tài)存儲(chǔ)…… 好像不行……
            boost.signal肯定是要?jiǎng)佑脛?dòng)態(tài)存儲(chǔ)的。】
            嗯。主要是管理起來很容易了,任何的參數(shù)直接綁定進(jìn)去就行了,不用自己弄個(gè)堆對(duì)象來保存,然后還要記得刪除。

            re: GUI框架:消息檢查者 cexer 2009-11-23 20:09
            @陳梓瀚(vczh)
            【function的好處就是你可以使用子類的同時(shí)不用管delete啊】
            想了下用 tr1::function 來實(shí)現(xiàn)確實(shí)要比手寫類簡(jiǎn)單得多,函數(shù)和參數(shù)綁定功能在這里很有用處,有多少參數(shù)都不用搞個(gè)多態(tài)的 Data 了,也不用自己去 delete 。確實(shí)很強(qiáng)大。

            re: GUI框架:消息檢查者 cexer 2009-11-23 17:31
            @陳梓瀚(vczh)
            【要堅(jiān)定不移地使用這些東西。 使用tr1::function<bool(Message&)>,毫無管理復(fù)雜性,幾乎沒有效率成本。】
            把 MessageChecker::isOk(const Message&) 的實(shí)現(xiàn)放到 bool MessageChecker::operator()(const Message&) 中去,函數(shù)體MessageChecker 就變成了和 function 類似的東西,但這樣又有什么本質(zhì)區(qū)別呢。tr1::function 的功能雖然強(qiáng)大,用它去實(shí)現(xiàn)消息檢查者,該寫的邏輯還得寫,省不了功夫,擴(kuò)展性也是個(gè)問題。

            【至于什么是框架什么是類庫(kù),有一個(gè)很容易的判斷標(biāo)準(zhǔn):template method就是框架。】
            謝謝,很多書對(duì)這個(gè)也言之不詳,只是叫著爽就行了,所以我自己也就不大明白。我從此以后照你這個(gè)標(biāo)準(zhǔn)去評(píng)判好了。

            【而且,千萬不要去考慮標(biāo)準(zhǔn)庫(kù)里面什么類的性能如何的問題,你永遠(yuǎn)假定他們是用魔法完成的,不需要任何CPU周期。不然你一行代碼都寫不出來。】
            我是從不考慮那些的:標(biāo)準(zhǔn)庫(kù)的效率再差,也不會(huì)到我放棄使用它們的地步的。另外以我的水平寫出來的東西絕對(duì)比它的慢,哪有資格嫌棄人家。

            【但是實(shí)際上windows的消息很亂,事件跟消息并不是一一對(duì)上號(hào)的。因此MessageChecker之類的東西最終用戶是看不到的,你要根據(jù)每一個(gè)控件的具體情況,重新整理出一系列事件,才能讓用的時(shí)候真正爽快起來。這里沒有技術(shù)問題。】
            你說得對(duì),框架用戶是看不到 MessageChecker 的,他們看到的是 onCreated,onClosed,onClicked 之類的東西。

            re: GUI框架:消息檢查者 cexer 2009-11-23 16:57
            @陳梓瀚(vczh)
            【繼續(xù)攪局:你憑什么認(rèn)為MessageChecker父類的成員變量一定夠用呢?如果夠用的話,就證明你的邏輯已經(jīng)是固定的了,為什么要子類?就一個(gè)MessageChecker好了,不用繼承。你矛盾了。】
            歡迎攪局!你提出一問題確實(shí)有“以子之矛攻子之盾”的殺傷力,不過幸好我不是既賣矛又賣盾的。關(guān)于數(shù)據(jù)不夠用的情況 OwnWaterloo 的也提出過,你可以倒著往上看給 OwnWaterloo 的回復(fù),在 MessageChecker 當(dāng)中加一個(gè)多態(tài)的 Data 成員可以放下所有東西,我還是把這東西更新到博文里去吧免得又有人問。“邏輯”的關(guān)鍵顯然不是數(shù)據(jù),而是那個(gè)檢查的動(dòng)作。就像銀行存了五千萬,不拿出去揮霍也住不上豪宅一樣,成員變量夠用成員函數(shù)不夠用也是白搭,必須得要改寫。要想一個(gè)類,不繼承,不改寫,而要滿足不斷出現(xiàn)的需求,這肯定是不能完成的任務(wù)。“數(shù)據(jù)夠用”和“函數(shù)改寫”并矛盾。

            【類的靈活性在于,你使用shared_ptr<Base>保存了一個(gè)Derived*,然后調(diào)用虛函數(shù)。代價(jià)非常低,我經(jīng)常把智能指針放進(jìn)容器,也可以不管誰去釋放,總之會(huì)被釋放。而且我這種寫compiler的人對(duì)循環(huán)引用十分敏感所以我基本不會(huì)犯這種錯(cuò)誤……】
            你是建議我把 MessageChecker 在堆上生成用智能指針管理起來吧。我也覺得這樣確實(shí)可以使用真正強(qiáng)大的虛函數(shù),但這樣要付出每次都在堆上構(gòu)造的效率成本和管理上的復(fù)雜性,而實(shí)際上大多數(shù)情況下這樣的付出是不必的:在 Windows 的消息機(jī)制下,消息檢查大多數(shù)時(shí)候需要的數(shù)據(jù)是很少的,用 WPARAM 和 LPARAM 就可以裝下,但確實(shí)有需要在堆上保存數(shù)據(jù)的情況,所以我在 MessgaeChecker 增加了一個(gè)多態(tài)的 Data 成員來保存,它只有極少時(shí)候的才會(huì)從堆上生成,這樣盡量避免了堆上生成的復(fù)雜性和效率損失,而完成的功能又絲毫不減。

            re: GUI框架:消息檢查者 cexer 2009-11-23 10:17
            @OwnWaterloo
            【框架定義了輪廓線,由程序員去填充顏色。類庫(kù)提供調(diào)色板等工具,由程序員去繪制。】
            這句話比喻得很好。你把框架理解成一種束縛是覺得需要按照它規(guī)定的方式去使用,但類庫(kù)甚至 API 何嘗不是也有自己的規(guī)則。我理解的框架和類庫(kù)其基本目的都是一樣的:對(duì)繁瑣的細(xì)節(jié)進(jìn)行封裝,提供更為便利的接口。這當(dāng)中肯定會(huì)損失靈活性,畢竟魚和熊掌很難兼得。但我覺得框架其實(shí)是類庫(kù)的進(jìn)化后的身份,從字面意義上來講,“框架”看起來更有彈性,擴(kuò)展的意思。但實(shí)際上大家對(duì)這兩個(gè)詞的概念并沒有很明白的分辨,比如說到 MFC,有人說框架有人說類庫(kù)大家的感覺都是一樣的。

            【這個(gè),其實(shí)也是反的……OO是思想,class只是它的一種實(shí)現(xiàn)方式。也許使用會(huì)比較方便。但靈活性是不如函數(shù)+數(shù)據(jù)的。】
            我的想法相反。你說類的靈活性不如函數(shù)加數(shù)據(jù),但類難道不正是建立在函數(shù)和數(shù)據(jù)之上的一個(gè)超強(qiáng)結(jié)合體?之所以用C之類的 OP 語言實(shí)現(xiàn)模式不如C++這樣的 OO 語言容易,一大原因正是它缺少類的支持。

            【message_checker ButtonClickingChecker(WORD id);
            message_checker xxxChecker( ... );】
            這是你舉例說明的用函數(shù)來實(shí)現(xiàn)檢查者。你可以嘗試真的用函數(shù)來實(shí)現(xiàn)消息檢查者,這個(gè) ButtonClickingChecker(WORD id) , xxxChecker( ... ) 函數(shù)內(nèi)部你各自要怎么實(shí)現(xiàn)?它既要包含不同的數(shù)據(jù),又要包含不同的操作,它們返回完全相同的 message_checker 對(duì)象,這個(gè) message_checker 又要怎么實(shí)現(xiàn)才能以一已之身完成眾多不同的功能?由于不同參數(shù)列表的函數(shù)實(shí)際上是完全不同的東西,你甚至不能以統(tǒng)一的方式保存它們管理它們。

            re: GUI框架:消息檢查者 cexer 2009-11-22 21:21
            cppblg 這爛程序,吃空格太嚴(yán)重了。

            re: GUI框架:消息檢查者 cexer 2009-11-22 21:05
            【不過我想了一個(gè)例子,比如我要在xxx-yyy時(shí)間段內(nèi),檢查這個(gè)消息,返回真,這個(gè)時(shí)間段外,就返回假。
            這個(gè)checker就做不到了。 肯定要放到其他地方做,比如hanlder中。】
            是可以的啊,可以像下面這樣實(shí)現(xiàn)。
                class TimeMessageChecker:public MessageChecker
                {
                public:
                    TimeMessageChecker( timeStart,timeTo )
                        :MessageChecker( 0,timeStart,timeTo,&TimeMessageChecker:virtualIsOk )
                    {}
                protected:
                    static bool virtualIsOk( const MessageChecker* pthis,const Message& )
                    {
                        timeNow   = GetCurrentTime();
                        timeStart = pthis->wparam;
                        timeTo    = pthis->lparam;
                        return timeNow>=timeStart && timeNow<=timeTo;
                    }
                }

            可能你的意思是遇到消息參數(shù)裝不下檢查時(shí)需要的信息的情況應(yīng)該怎么辦,這里舉例說明一下怎么實(shí)現(xiàn)。比如說要檢查是否某個(gè)字符串,這樣的實(shí)現(xiàn)可以裝下任何需要的信息。
            先定義一個(gè)多態(tài)的數(shù)據(jù)類型,為了效率這里可以使用引用計(jì)數(shù)之類的東西
                class MessageData
                {
                public:
                    virtual ~MessageData()
                    {}
                    virtual void release()
                    {
                        delete this;
                    }
                    virtual MessageData* clone() const = 0;
                };

            MessageChecker 當(dāng)中有這個(gè)成員
                class MessageChecker
                {
                //......
                public:
                    MessageData* data;
                }

            修改拷貝構(gòu)造函數(shù)和析構(gòu)函數(shù)
                MessageChecker::MessageChecker( const MessageChecker& other )
                {
                    if ( data )
                    {
                        data->release();
                        data = NULL;
                    }
                    if ( other.data )
                    {
                        data = other.data->clone();
                    }
                }

                MessageChecker::~MessageChecker()
                {
                    if ( data )
                    {
                        data->release();
                        data = NULL;
                    }
                }

            定義一個(gè)裝字符串的多態(tài)數(shù)據(jù)類
                class StringMessageData:public MessageData
                {
                public:
                    StringMessageData( const String& str_ )
                        :string( str_ )
                    {}
                    virtual MessageData* clone() const
                    {
                        return new StringMessageData(string);
                    }
                public:
                    String  string;
                };

            利用數(shù)據(jù)成員 data 所裝的信息可以檢查字符串的消息檢查者
                class StringMessageChecker:public MessageChecker
                {
                public:
                    StringMessageChecker( const String& string )
                        :MessageChecker( 0,0,0,&StringMessageChecker::virutalIsOk )
                    {
                        data = new StringMessageData( string );
                    }
                public:
                    static bool virtualIsOk( const MessageChecker* pthis,const Message& message )
                    {
                        StringMessageData* data = (StringMessageData*)pthis->data;
                        if ( !data )
                        {
                            return false;
                        }
                        std::string stirngToCheck = (const Char*)( message.wparam );
                        return stirngToCheck == data->string;
                    }
                };

            【對(duì),這就是我對(duì)"框架"感到反感的地方之一 —— 它"限制"你做事的方法。不對(duì)它熟悉到一定程度,就沒法工作……
            作為程序員……我也了解用戶的需求是很惡心的…… 就像你有一篇blog里寫的那樣……所以,推己及人……對(duì)我提出的這個(gè)惡心的需求,聽過之后就當(dāng)是廢話好了~_~】
            說實(shí)話我一直對(duì)“框架”和“類庫(kù)”的概念分不大清楚,我想“框架”從名字上來說多了一個(gè)“可以擴(kuò)展,可以填充”的意思,沒有你說的“限制你做事的方法”這種感覺。還有你提到了 GUI 框架用戶的需求。要說明一下的是,實(shí)現(xiàn)的這個(gè)消息檢查者只是在框架內(nèi)工作的,方便 GUI 框架的開發(fā)者和擴(kuò)充者使用,GUI 框架的使用者不會(huì)接觸到這個(gè)東西。最終的用戶只需要使用是像這個(gè)樣子:
                window.onCreated += messageHandler( &::_handleCreated );
                window.onCreated += messageHandler ( this,&Window::_handleCreated );

            共4頁(yè): 1 2 3 4 
            99久久777色| 无码久久精品国产亚洲Av影片| 久久er国产精品免费观看2| 久久WWW免费人成—看片| 99久久99久久精品国产片果冻| 久久久久无码精品国产不卡| 久久精品国产99国产精品| 99精品国产在热久久无毒不卡| 亚洲国产成人久久综合一| 久久久久久亚洲AV无码专区 | 亚洲成av人片不卡无码久久| 久久久久久夜精品精品免费啦| 99久久国产热无码精品免费久久久久| 人妻无码久久精品| 精品精品国产自在久久高清| 久久久无码精品亚洲日韩京东传媒| 精品国产乱码久久久久久浪潮| 老男人久久青草av高清| 久久久艹| 天天久久狠狠色综合| 99热都是精品久久久久久| 久久综合九色综合久99| 人妻精品久久久久中文字幕69 | 久久久精品视频免费观看 | 久久91精品综合国产首页| 亚洲va中文字幕无码久久不卡| 久久精品无码免费不卡| 国产99久久精品一区二区| 国内精品久久久人妻中文字幕| 亚洲国产成人久久综合野外| 91麻豆精品国产91久久久久久| 伊人久久精品无码av一区| 综合久久给合久久狠狠狠97色| 久久久精品人妻无码专区不卡| 久久综合狠狠综合久久激情 | 久久99国产综合精品免费| 亚洲精品乱码久久久久久久久久久久 | 中文字幕乱码久久午夜| 亚洲日本va午夜中文字幕久久| 久久夜色撩人精品国产小说| 欧美精品福利视频一区二区三区久久久精品 |