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

            huaxiazhihuo

             

            略說成員函數(shù)指針及其模板的精簡實現(xiàn)

                請容許先發(fā)一句牢騷,“這萬惡的成員函數(shù)指針的丑陋語法!”,C中的函數(shù)指針的語法已經(jīng)夠難看的了,但相比之下,成員函數(shù)指針卻更加不堪入目,使用上又很不方便,很不人性化,簡直是只能行走寸步。只可惜,函數(shù)指針的作用實在太大了,忽視不得。
                大家都知道,函數(shù)指針(或又叫回調函數(shù))是上層模塊和底層模塊進行通信的最佳手段,上層通過提供函數(shù)指針給底層,以使得底層在適當?shù)臅r候,可以調用執(zhí)行上層的代碼,C庫中的qsort足以說明這種使用,qsort在排序時,不知道如何比較兩個數(shù)組元素的大小,必須通過上層提供的大小比較函數(shù)來進行比較。此外,操作系統(tǒng)提供的API中,有多少地方使用上了回調函數(shù)。假如沒有函數(shù)指針,這簡直沒法想像,日子沒法過了。函數(shù)指針是實現(xiàn)模塊分層的不二法門,當然接口也可以,但是,用戶代碼必須繼承或者實現(xiàn)底層硬性規(guī)定無理取鬧的虛函數(shù),本來很輕量級的POD,再也不輕快了,實在頗不方便,不,簡直很有點惡心。說來說去,還是函數(shù)指針好。
                既然,C中的回調函數(shù)這么重要,那么,可想而知,進入C++中,整個世界到處都是CLASS,將回調函數(shù)這個概念推廣到CLASS上,也即是成員函數(shù)指針,將是多么迫切的事情。理論上,可以將成員函數(shù)指針視為函數(shù)指針的語法糖,只要規(guī)定函數(shù)指針的第一個參數(shù)為void* pThis,然后在函數(shù)指針的實現(xiàn)函數(shù)中,進行類型轉換也能滿足使用,在很長的一段時間里,因為這種方式的簡單清晰,一直都用這種方式代替成員函數(shù)指針。但是,一遍又一遍地被迫編寫重復代碼,特別是枯燥的類型轉換,任何人都無法忍受。因此,決定直面這個問題。
                理論上,成員函數(shù)和普通函數(shù)一樣,在內存中,都有自己的位置,只要有了地址信息,就可以通過指針來獲取,保存起來,然后在未來的某個地方,通過這個指針來執(zhí)行函數(shù)中的代碼。差別之處,在于,調用成員函數(shù)前,要先將this推入ecx中,很久之前,成員函數(shù)指針確實和普通函數(shù)指針一樣簡單,只是后來,虛函數(shù)和多繼承出現(xiàn)之后,簡單的指針信息再也承載不了成員函數(shù)的重量,從此之后,.......(忽略,請大家自行BAIDU)。總之,C++中,成員函數(shù)指針并非指針類型,理所當然,也就不支持指針的大多數(shù)操作,比如,賦值NULL,或者類型轉換。因此,所有能夠讓函數(shù)指針大放異彩的種種手段,在這里,都用不上了,原本在C中光芒四射的好東西,到了C++中,竟然黯然失色,所有本該讓函數(shù)指針大顯身手的地方,大家都繞道而行。
                逼急了,也有嘗試突破,MFC的僅僅作了有限爭取的手段(為了這一點點好處,MFC可不知作了多大的努力),居然成為其消息映射的基石。但是,據(jù)說,MFC的成員函數(shù)指針的設計也非出于自愿,而是因為消息太多,實在沒法整成虛函數(shù)來處理,每個窗口類背負成千上萬個函數(shù)的虛函數(shù)表,可不是省油的燈。為了努力地支持虛函數(shù)和多繼承,C++的編譯器不惜在成員函數(shù)指針的使用上設下種種阻攔,令人又氣又恨。而更加令人不解的是,C++橫行天下十幾年,函數(shù)指針似乎長期得不到重視,大師們都在面向對象上探索,很多本該成員函數(shù)指針發(fā)光發(fā)熱的地方,幾乎都退位給虛函數(shù)了,并美其名曰策略模式又或者是其他的什么模式,不過是換了一套更加難看的馬甲,卻又那么好聽的名字,不,不好聽,只要聽到模式兩字,就令人大倒胃口。所有大用特用模式的代碼,如果用非模式來實現(xiàn),其代碼量將少掉很多,而且還更具擴展性,這是真的。先透露一下,正在構思一文章,將深度介紹模式,專注于WHY,并且類比現(xiàn)實,兼扯上WINDOWS、COM和MFC對模式的應用,說句良心話,如果只用接口來做設計,模式絕對是好東西。只可惜,接口其實是SB。寫底層代碼,如果要求用戶必須實現(xiàn)某些接口,又或者是繼承某些類,改寫虛函數(shù),這種侵入式的設計,實在無理取鬧之至。
                后來,大伙兒也終于開始重視成員函數(shù)指針,特別是C#的委托出現(xiàn)之后,網(wǎng)絡上更是充斥著各種成員函數(shù)指針的版本代碼,都可以很好地完成任務。特別是TR1又或者是BOOST中的function,功能相當?shù)膹姾返昧钊朔谴蟪砸惑@不可。只可惜,大多數(shù)情況下,用戶只想填飽肚子而已,但是BOOST或者其他的類庫卻硬要來一桌滿漢全席,這也罷了,但是,它還要用戶額外買單,并且還真不低呢,這就很讓人受不了啦。其實,一般情況下,我們的要求不會太過分,僅僅想要針對普通的成員函數(shù)指針進行回調,它卻為此在其內部new一個內部類出來,假如大規(guī)模使用,后果將不堪設想,其實也沒那么嚴重,完成是C++迷們的強迫癥。
                但是,說真的,實在希望很精簡,不要生成不必要的虛函數(shù)表,不要模板生成不必要的函數(shù)(沒辦法內聯(lián),有函數(shù)地址的那一種),只要求它如同對待C中的函數(shù)指針一樣,參數(shù)入棧和一個簡單的函數(shù)調用的指令,外加將this推入ecx即可,就好像直接調用成員函數(shù)那樣就好了。好了,貢獻上代碼了,史上最輕量級,精簡無比的成員函數(shù)指針,功能也最弱了。對不起,代碼并不完整,實際的代碼,用上了宏,所謂的宏的圖靈完備。在下很懶,一向只介紹想法而已,只于具體的實現(xiàn)細節(jié)以及語法考究,竊以為,每個C++迷們應該完全能夠勝任。俗話說,高手只要求創(chuàng)意就行了,本文詳細介紹算法并給出代碼,已經(jīng)落了下乘。
                這個實現(xiàn),不考慮多繼承,忽略了虛函數(shù),也不支持非成員函數(shù)(也可以用上,只是,要多做一點點手腳,以下將給出示例,而且,普通函數(shù)指針已經(jīng)完全可以勝任),只集中火力專注于普通成員函數(shù),畢竟,在下的運用中,它占上了95%以上,所以才能如此的高效。單一職責啊!
                此外,本文參考了《成員函數(shù)指針與高性能的C++委托》、《劉未鵬的BOOST源碼解析》、《C++設計新思維》,請自行GOOGLE。
            template <class OutputClass, class InputClass>
            union horrible_union{
                OutputClass 
            out;
                InputClass 
            in;
            };

            template 
            <class OutputClass, class InputClass>
            inline 
            void union_cast(OutputClass& outconst InputClass input){
                horrible_union
            <OutputClass, InputClass> u;
                typedef 
            int ERROR_CantUseHorrible_cast[sizeof(InputClass)==sizeof(u) 
                    
            && sizeof(InputClass)==sizeof(OutputClass) ? 1 : -1];
                u.
            in = input;
                
            out = u.out;
            }

            template
            <typename FuncSignature>class TMemFn;
            class CCallbackObject{};

            template
            <typename R>
            class TMemFn<R ()>
            {
            public:
                typedef R ReturnType;
                ReturnType 
            operator()() const{return (pThis->*func)();}

                template
            <typename _Ty>
                
            void Bind(_Ty* pObj, R(_Ty::*proc)())
                {
                    union_cast(pThis, pObj);
                    union_cast(func, proc);
                }

            public:
                typedef ReturnType (CCallbackObject::
            *FuncType)();
                FuncType func;
                CCallbackObject
            * pThis;
            };

            template
            <typename R, typename P1>
            class TMemFn<R (P1)>
            {
            public:
                typedef R ReturnType;
                typedef P1 Param1Type;

                ReturnType 
            operator()(Param1Type param1) const{return (pThis->*func)(param1);}

                template
            <typename _Ty>
                
            void Bind(_Ty* pObj, ReturnType(_Ty::*proc)(Param1Type))
                {
                    union_cast(pThis, pObj);
                    union_cast(func, proc);
                }

            public:
                typedef ReturnType (CCallbackObject::
            *FuncType)(Param1Type);
                FuncType func;
                CCallbackObject
            * pThis;
            };

            template
            <typename R, typename _Ty>
            TMemFn
            <R ()> MakeMF(_Ty* pThis, R(_Ty::*proc)())
            {
                TMemFn
            <R ()> res; res.Bind(pThis, proc);
                
            return res;
            }

            template
            <typename R, typename _Ty, typename P1>
            TMemFn
            <R (P1)> MakeMF(_Ty* pThis, R(_Ty::*proc)(P1))
            {
                TMemFn
            <R (P1)> res;res.Bind(pThis, proc);
                
            return res;
            }

            int Test(int a)
            {
                printf(
            "Hello World %d\n", a);
                
            return a;
            }

            int _tmain(int argc, _TCHAR* argv[])
            {
                
            class _CTest
                {
                
            public:
                    
            int CallTest(int a)
                    {
                        
            return Test(a);
                    }
                };
                TMemFn
            <int (int)> aTest = MakeMF((_CTest*)NULL, &_CTest::CallTest);
                aTest(
            80);
                
            return 0;
            }

            posted on 2012-11-16 10:46 華夏之火 閱讀(2938) 評論(4)  編輯 收藏 引用 所屬分類: c++技術探討

            評論

            # re: 略說成員函數(shù)指針及其模板的精簡實現(xiàn) 2012-11-16 17:32 Richard Wei

            還是直接用C++ 11中的function吧  回復  更多評論   

            # re: 略說成員函數(shù)指針及其模板的精簡實現(xiàn) 2012-11-16 17:55 華夏之火

            @Richard Wei
            直接用function,會有心理負擔,雖然沒有必要  回復  更多評論   

            # re: 略說成員函數(shù)指針及其模板的精簡實現(xiàn) 2012-11-22 07:39 fzy

            其實一切源于

            typedef TRET (TClass::*P_METHOD)( TPARAM... );
            typedef TRET (__cdecl *P_FUNC_CDECL)( TPARAM... );
            typedef TRET (__stdcall * P_FUNC_STDCALL)( TPARAM... );
            typedef TRET (__fastcall * P_FUNC_FASTCALL)( TPARAM... );

            剩下的就是解決
            TRET 和 TPARAM... 類型以及 P_METHOD/P_FUNC_XXXXX 的打包問題。

            中間比較繁瑣的是 TRET 的void 特例,以及TPARAM...的傳參類型。

            在某些特定環(huán)境下,還需要考慮TPARAM...的存儲類型。

            不過c++的template有特化來實現(xiàn)這些東西,所以最后都歸結到工作量了。  回復  更多評論   

            # re: 略說成員函數(shù)指針及其模板的精簡實現(xiàn) 2012-11-22 09:27 華夏之火

            @fzy
            有必要支持那么多嗎,只要typedef TRET (TClass::*P_METHOD)( TPARAM... )這一個就行了,void 確實比較特別  回復  更多評論   

            導航

            統(tǒng)計

            常用鏈接

            留言簿(6)

            隨筆分類

            隨筆檔案

            搜索

            積分與排名

            最新評論

            閱讀排行榜

            評論排行榜

            久久亚洲欧美国产精品| 精品水蜜桃久久久久久久| 亚洲国产视频久久| 一本一本久久a久久综合精品蜜桃| 亚洲精品无码专区久久同性男| 国产成人精品综合久久久久| 国产精品久久久久久久| 久久91这里精品国产2020| 亚洲人成网亚洲欧洲无码久久| 狠狠色婷婷综合天天久久丁香 | 武侠古典久久婷婷狼人伊人| 中文字幕乱码人妻无码久久| 亚洲天堂久久精品| 国产激情久久久久久熟女老人| 免费国产99久久久香蕉| 青青草原综合久久大伊人| 曰曰摸天天摸人人看久久久| 久久久久久久久久久精品尤物| 一本大道久久a久久精品综合| 国内精品伊人久久久影院| 丁香久久婷婷国产午夜视频| 久久亚洲欧美国产精品| 免费无码国产欧美久久18| 久久99精品国产麻豆婷婷| 精品综合久久久久久97超人 | 久久综合给合久久狠狠狠97色 | 性做久久久久久久久久久| 亚洲国产精品人久久| 国产一区二区精品久久| 无码AV波多野结衣久久| 国产香蕉久久精品综合网| 亚洲精品无码久久久| 亚洲精品无码专区久久同性男| 久久久久国产精品麻豆AR影院| 亚洲国产精品久久久久久| 久久这里只精品国产99热| 久久精品国产免费| 激情五月综合综合久久69| 国产免费久久精品99久久| 国产—久久香蕉国产线看观看| 亚洲国产精品久久久久网站|