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

            牽著老婆滿街逛

            嚴(yán)以律己,寬以待人. 三思而后行.
            GMail/GTalk: yanglinbo#google.com;
            MSN/Email: tx7do#yahoo.com.cn;
            QQ: 3 0 3 3 9 6 9 2 0 .

            泛化仿函數(shù)用法及參數(shù)綁定的問題

            from:http://blog.csdn.net/dog_in_yellow/archive/2007/02/15/1510538.aspx


                 《C++設(shè)計(jì)新思維》一書里的泛化仿函數(shù)從Command模式講起。Command模式主要用來降低系統(tǒng)中命令的調(diào)用者和執(zhí)行者間的依存性。設(shè)計(jì)模式的書里面一般都采用多態(tài)的機(jī)制,調(diào)用者持有Command對象的基類接口,在此處我們稱為Command接口,Command接口不知道自己將被用于執(zhí)行什么命令,一般只包含一個(gè)觸發(fā)命令執(zhí)行的虛函數(shù),假設(shè)名為Excute。各種不同的實(shí)際執(zhí)行命令的Command對象從則Command接口派生,并重寫Excute虛函數(shù)。這樣調(diào)用者通過Command接口來觸發(fā)命令執(zhí)行時(shí),因?yàn)樘摵瘮?shù)機(jī)制的關(guān)系,實(shí)際上調(diào)用的都是從Command接口派生的Command對象的Excute函數(shù)。在這樣的設(shè)計(jì)中,調(diào)用者和各種實(shí)際的命令對象互不相見,只持有一個(gè)Command接口。在C風(fēng)格的設(shè)計(jì)中,一般用回調(diào)預(yù)先保存的函數(shù)指針來實(shí)現(xiàn)Command模式。

                泛化仿函數(shù)可以說是一種回調(diào),但它不但可以保存函數(shù)指針,還可以處理實(shí)現(xiàn)了operator()的C++對象,C++對象的成員函數(shù)。具體實(shí)現(xiàn)方法書里面已描述得非常詳細(xì),就不再多啰嗦,在此主要說一下項(xiàng)目中運(yùn)用泛化仿函數(shù)的一些心得?;救缦掠梅ǎ?br>Functor<RETURN_TYPE,PARAM_TYPE_LIST> cmd1(...);
            Functor有兩個(gè)泛型參數(shù),第一個(gè)為函數(shù)返回值,第二個(gè)為函數(shù)的參數(shù)列表。構(gòu)造函數(shù)可接受仿函數(shù)、類成員函數(shù)以及一般函數(shù)指針。下面示例代碼演示了其用法: 

            #include "loki/functor.h"
            #include 
            <iostream>
            #include 
            <string>
            using namespace std;
            using namespace Loki;

            struct TestFunctor
            {
                
            int operator()(string str)
                
            {
                    cout 
            << str << endl;
                    
            return 0;
                }

            }
            ;

            struct TestFunctor2
            {
                
            int output(int i)
                
            {
                    cout 
            << i << endl;
                    
            return 2;
                }

            }
            ;

            void TestFunction(int i,int j)
            {
                cout 
            << i << "," << j << endl;
            }


            Functor
            <int,NullType> BindCmd1()
            {
                TestFunctor f;

                Functor
            <int,LOKI_TYPELIST_1(string> cmd1( f );
                Functor
            <int,NullType> bcmd1 = BindFirst( cmd1, "another bind cmd1" );

                
            return bcmd1;
            }


            int _tmain(int argc, _TCHAR* argv[])
            {
                
            //泛化仿函數(shù)基本用法
                
            //Functor<RETURN_TYPE, PARAM_TYPELIST> cmd(...);

                TestFunctor f;
                TestFunctor2 f2;

                
            //調(diào)用operator()仿函數(shù)----------------------------
                Functor<int,LOKI_TYPELIST_1(string> cmd1( f );
                cmd1( 
            "1" );
                
            //end of 調(diào)用operator()仿函數(shù)----------------------


                
            //調(diào)用類成員函數(shù)----------------------------------
                Functor<int,LOKI_TYPELIST_1(int> cmd2( &f2,  &TestFunctor2::output );
                cmd2( 
            2 );
                
            //end of調(diào)用類成員函數(shù)------------------------------


                
            //調(diào)用一般函數(shù)指針---------------------------------
                Functor<void,LOKI_TYPELIST_2(int,int> cmd3( TestFunction );
                cmd3( 
            3,4 );
                
            //end of調(diào)用一般函數(shù)指針---------------------------

                
            //預(yù)先綁定命令的參數(shù)的調(diào)用1
                Functor<int,NullType> bcmd1 = BindFirst( cmd1, "bind cmd1" );
                bcmd1();
                
            //end of 預(yù)先綁定命令的參數(shù)的調(diào)用1

                
            //預(yù)先綁定命令的參數(shù)的調(diào)用2
                Functor<int,NullType> bcmd1_1 = BindCmd1();
                bcmd1_1();
                
            //end of 預(yù)先綁定命令的參數(shù)的調(diào)用2


                
            return 0;
            }

                用法很簡單,上面的幾個(gè)用法都只有兩行,第一行定義泛化仿函數(shù),第二行執(zhí)行仿函數(shù)。實(shí)際運(yùn)用中定義和執(zhí)行一般都各在不同的地方,如Command模式一樣,即它們在時(shí)間和空間上是分離的。

                如果您使用了LOKI0.1.5的庫,在“預(yù)先綁定命令的參數(shù)的調(diào)用2”的用法中會出現(xiàn)運(yùn)行時(shí)錯(cuò)誤,這是我在項(xiàng)目過程中碰到的,經(jīng)過分析LOKI中Functor實(shí)現(xiàn)的代碼,終于找到了原因。項(xiàng)目中實(shí)際的運(yùn)用當(dāng)然不是這樣,示例代碼只說明了在什么情況下運(yùn)用才會出錯(cuò)。如代碼所示,調(diào)用綁定了參數(shù)的仿函數(shù)時(shí),如果已經(jīng)離開了所綁定參數(shù)的作用域則會出錯(cuò)。而其罪魁禍?zhǔn)自谟趯壎ǖ膮?shù)作了優(yōu)化。

              《C++設(shè)計(jì)新思維》P123中講到為避免函數(shù)轉(zhuǎn)發(fā)的成本對函數(shù)參數(shù)作了優(yōu)化,如果參數(shù)為非基本類型(非內(nèi)置類型,如自定義的struct,class),則將參數(shù)類型更改為該參數(shù)的引用類型。如示例中的int operator()(string str)被優(yōu)化后str參數(shù)變成string &str。而當(dāng)一個(gè)引用已離開其所引用對象的作用域后,該引用會成為一個(gè)dead reference,使用了dead reference,不可避免地結(jié)局就是運(yùn)行時(shí)錯(cuò)誤?;蛟S作者不許我們這么使用綁定參數(shù),或者作者沒想到我們會這么使用綁定,但至少說明了一點(diǎn),過多地優(yōu)化未必是件好事。

                既然知道了為什么會出錯(cuò),那就容易解決問題了。綁定的原理是將參數(shù)保存起來,在調(diào)用的時(shí)候取出預(yù)先保存的參數(shù)傳遞給要調(diào)用的函數(shù)。如果保存的類型是值類型,那不管是否離開原參數(shù)的作用域都不會出錯(cuò)?,F(xiàn)在我們來找實(shí)現(xiàn)參數(shù)綁定的類定義。在Functor.h中找到class BinderFirst,該類中有一個(gè) 類型定義如下:
            typedef typename Private::BinderFirstBoundTypeStorage<
             typename Private::BinderFirstTraits<OriginalFunctor>
             ::OriginalParm1>::RefOrValue
             BoundTypeStorage;
            BoundTypeStorage即保存所綁定參數(shù)的類型定義,觀其定義可以知道該類型也是做了優(yōu)化,非基本類型都變成了引用?,F(xiàn)在我們來做一點(diǎn)小改動(dòng),使用參數(shù)原來的類型來保存參數(shù),修改后的定義如下:
            typedef typename Private::BinderFirstTraits<OriginalFunctor>
               ::OriginalParm1
               BoundTypeStorage;
            修改完畢后,重新編譯運(yùn)行,一切OK了。

                其實(shí)上述改動(dòng)并不能解決所有問題,這種做法是使用參數(shù)的原始類型來保存參數(shù),假如參數(shù)本身是個(gè)引用類型,那在離開了所引用對象的作用域時(shí)調(diào)用還是會出錯(cuò)的。最徹底的改法是將引用參數(shù)去掉引用作為保存參數(shù)的類型。我的做法是在使用的時(shí)候做文章,不管參數(shù)是否引用類型,定義綁定的Functor時(shí)都定義成非引用類型,這樣再配合上面的改動(dòng),參數(shù)必然會使用值類型保存。如果明確地知道調(diào)用時(shí)不會離開原參數(shù)的作用域,那就不必如此了。只要心中有個(gè)底,具體用法就視個(gè)人運(yùn)用的環(huán)境以及個(gè)人做法的喜好了。

            LOKI0.1.5下載地址:http://sourceforge.net/forum/forum.php?forum_id=583500

            posted on 2007-09-03 16:02 楊粼波 閱讀(502) 評論(0)  編輯 收藏 引用

            日本精品久久久久中文字幕8| 久久婷婷五月综合色奶水99啪| 色8激情欧美成人久久综合电| 亚洲国产精品久久久久婷婷老年 | 久久伊人五月天论坛| 精品无码久久久久久午夜| 久久Av无码精品人妻系列| 久久精品无码专区免费东京热 | 伊人色综合久久天天人手人婷| 一级做a爰片久久毛片毛片| 午夜精品久久久久久久无码| 热99RE久久精品这里都是精品免费 | 婷婷久久香蕉五月综合加勒比| 久久偷看各类wc女厕嘘嘘| 久久福利青草精品资源站| 久久久久久噜噜精品免费直播| 香蕉久久夜色精品国产2020| 久久综合九色综合网站| 69国产成人综合久久精品| 久久久久亚洲AV无码专区桃色| 久久午夜夜伦鲁鲁片免费无码影视 | 久久精品极品盛宴观看| 无码国产69精品久久久久网站| 国产精品久久久天天影视香蕉 | 精品久久久无码中文字幕天天| 欧美精品国产综合久久| 狠狠色丁香婷综合久久| 久久精品国产AV一区二区三区| 国产精品久久久久久久久| 超级碰碰碰碰97久久久久| 青青青国产精品国产精品久久久久| 婷婷久久精品国产| 国产精品久久久99| 久久电影网一区| 国产精品久久久久久久久| 中文字幕久久精品 | 久久精品亚洲日本波多野结衣 | 男女久久久国产一区二区三区| 蜜桃麻豆WWW久久囤产精品| 久久精品国产只有精品66| 丰满少妇高潮惨叫久久久|