• <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>
            隨筆-167  評(píng)論-8  文章-0  trackbacks-0

            跟諸如Object Pascal和Ada等其它一些語(yǔ)言不同,C++語(yǔ)言并沒(méi)有內(nèi)在地提供一種將類的方法作為回調(diào)函數(shù)使用的方案。在C語(yǔ)言中,這種回調(diào)函數(shù)被稱作算子(functor),在事件驅(qū)動(dòng)類程序中普遍存在。主要問(wèn)題基于這樣一個(gè)事實(shí):某個(gè)類的多個(gè)實(shí)例各自位于內(nèi)存的不同位置。這就需要在回調(diào)的時(shí)候不僅需要一個(gè)函數(shù)指針,同時(shí)也需要一個(gè)指針指向某個(gè)實(shí)例本身(譯者注:否則回調(diào)時(shí)便無(wú)法知道目前正在操作的是哪個(gè)對(duì)象,C++類的非靜態(tài)方法包含一個(gè)默認(rèn)的“參數(shù)”:this指針,就是起這種作用的)。所以,針對(duì)問(wèn)題的定義,有一個(gè)很直觀的解決方法就是使用模板和編譯時(shí)的實(shí)例化及特化。

             解決方案

             這里的方案只支持一個(gè)模板參數(shù),但如果一些能夠如愿的話,隨著更多的編譯器完全實(shí)現(xiàn)C++標(biāo)準(zhǔn),以后將會(huì)支持動(dòng)態(tài)的模板參數(shù),比如“…”形式的模板參數(shù)列表(參見《C++ Templates, The Complete Guide》),那時(shí),我們就可以可以實(shí)現(xiàn)無(wú)需全部預(yù)定義的參數(shù)集合。(文中所有代碼的注釋為譯者加,下同。)

             template < class Class, typename ReturnType, typename Parameter >
             class SingularCallBack
             {
               public:
            //指向類成員函數(shù)的指針,用他來(lái)實(shí)現(xiàn)回調(diào)函數(shù)。
             typedef ReturnType (Class::*Method)(Parameter);
                 //構(gòu)造函數(shù)
                 SingularCallBack(Class* _class_instance, Method _method)
                 {
                    class_instance = _class_instance;
                   method        = _method;
                 };
             //重載函數(shù)調(diào)用運(yùn)算符()
                 ReturnType operator()(Parameter parameter)
                 {
                    return (class_instance->*method)(parameter);
                 };
                 //與上面的()等價(jià)的函數(shù),引入這個(gè)函數(shù)的原因見下文
                 ReturnType execute(Parameter parameter)
                 {
                    return operator()(parameter);
             };
                private:
                 Class*  class_instance;
                 Method  method;
             };
             模板的使用

             模板(template)的使用非常方便,模板本身可被實(shí)例化為一個(gè)對(duì)象指針(object pointer)或者一個(gè)簡(jiǎn)單的類(class)。當(dāng)作為對(duì)象指針使用時(shí),C++有另外一個(gè)令人痛苦的限制:operator() 不可以在指針未被解引用的情況下調(diào)用,對(duì)于這個(gè)限制,一個(gè)簡(jiǎn)便的但卻不怎么優(yōu)雅的解決方法在一個(gè)模板內(nèi)部增加一個(gè)execute方法(method),由這個(gè)方法從模板內(nèi)部來(lái)調(diào)用operator()。除了這一點(diǎn)不爽之外,實(shí)例化SinglarCallBack為一個(gè)對(duì)象指針將可以使你擁有一個(gè)由回調(diào)組成的vector,或者任何其他類型的集合,這在事件驅(qū)動(dòng)程序設(shè)計(jì)中是非常需要的。
             假設(shè)以下兩個(gè)類已經(jīng)存在,而且我們想讓methodB作為我們的回調(diào)方法,從代碼中我們可以看到當(dāng)傳遞一個(gè)class A類的參數(shù)并調(diào)用methodB時(shí),methodB會(huì)調(diào)用A類的output方法,如果你能在stdout上看到"I am class A :D",就說(shuō)明回調(diào)成功了。
             class A
             {
                public:
                void output()
                 {
                    std::cout << "I am class A :D" << std::endl;
                 };
             };
             class B
             {
                public:
                 bool methodB(A a)
                 {
                    a.output();
                    return true;
                 }
             };
             有兩種方法可以從一個(gè)對(duì)象指針上調(diào)用一個(gè)回調(diào)方法,較原始的方法是解引用(dereference)一個(gè)對(duì)象指針并運(yùn)行回調(diào)方法(即:operator()),第二個(gè)選擇是運(yùn)行execute方法。
             //第一種方法:
             A a;
             B b;
             SingularCallBack< B,bool,A >* cb;
             cb = new SingularCallBack< B,bool,A >(&b,&B::methodB);
             if((*cb)(a))
             {
                std::cout << "CallBack Fired Successfully!" << std::endl;
             }
             else
             {
               std::cout << "CallBack Fired Unsuccessfully!" << std::endl;
             }
             //第二種方法:
             A a;
             B b;
             SingularCallBack< B,bool,A >* cb;
             cb = new SingularCallBack< B,bool,A >(&b,&B::methodB);
             if(cb->execute(a))
             {
                std::cout << "CallBack Fired Successfully!" << std::endl;
             }
             else
             {
                std::cout << "CallBack Fired Unsuccessfully!" << std::endl;
             }
             下面的代碼示范了怎樣將一個(gè)模板實(shí)例化成一個(gè)普通的對(duì)象并使用之。
             A a;
             B b;
             SingularCallBack< B,bool,A >cb(&b,&B::methodB);
             {
                std::cout << "CallBack Fired Successfully!" << std::endl;
             }
             else
             {
                std::cout << "CallBack Fired Unsuccessfully!" << std::endl;
             }
             更復(fù)雜的例子,一個(gè)回調(diào)模板可以像下面這樣使用:
             class AClass
             {
               public:
                  AClass(unsigned int _id): id(_id){};
                 ~AClass(){};
                  bool AMethod(std::string str)
                  {
                     std::cout << "AClass[" << id << "]: " << str << std::endl;
                     return true;
                  };
                private:
                 unsigned int id;
             };
             typedef SingularCallBack < AClass, bool, std::string > ACallBack;
             int main()
             {
                std::vector < ACallBack > callback_list;
                AClass a1(1);
                AClass a2(2);
                AClass a3(3);
                callback_list.push_back(ACallBack(&a1, &AClass::AMethod));
                callback_list.push_back(ACallBack(&a2, &AClass::AMethod));
                callback_list.push_back(ACallBack(&a3, &AClass::AMethod));
                for (unsigned int i = 0; i < callback_list.size(); i++)
                {
                   callback_list[i]("abc");
                }
             
               for (unsigned int i = 0; i < callback_list.size(); i++)
               {
                  callback_list[i].execute("abc");
               }
             
               return true;
            }

            下面這個(gè)例子比上面的又復(fù)雜一些,你可以混合從同一個(gè)公共基類(base class)上繼承下來(lái)的不同的類到一個(gè)容器中,于是你就可以調(diào)用位于繼承樹的最底層的類的方法(most derived method)。(譯者注,C++的多態(tài)機(jī)制)
            class BaseClass
            {
               public:
                 virtual ~BaseClass(){};
                 virtual bool DerivedMethod(std::string str){ return true; };
            };

            class AClass : public BaseClass
            {
               public:
                 AClass(unsigned int _id): id(_id){};
                ~AClass(){};
                 bool AMethod(std::string str)
                 {
                    std::cout << "AClass[" << id << "]: " << str << std::endl;
                    return true;
                 };

                 bool DerivedMethod(std::string str)
                 {
                    std::cout << "Derived Method AClass[" << id << "]: " << str << std::endl;
                    return true;
                 };

               private:
                unsigned int id;
            };

            class BClass : public BaseClass
            {
               public:
                BClass(unsigned int _id): id(_id){};
                ~BClass(){};
                 bool BMethod(std::string str)
                 {
                    std::cout << "BClass[" << id << "]: " << str << std::endl;
                    return true;
                 };

                 bool DerivedMethod(std::string str)
                 {
                    std::cout << "Derived Method BClass[" << id << "]: " << str << std::endl;
                    return true;
                 };
               private:
                unsigned int id;

            };


            typedef SingularCallBack < BaseClass, bool, std::string > BaseCallBack;

            int main()
            {
               std::vector < BaseCallBack > callback_list;

               AClass a(1);
               BClass b(2);

               callback_list.push_back(BaseCallBack(&a, &BaseClass::DerivedMethod));
               callback_list.push_back(BaseCallBack(&b, &BaseClass::DerivedMethod));

               for (unsigned int i = 0; i < callback_list.size(); i++)
               {
                  callback_list[i]("abc");
               }

               for (unsigned int i = 0; i < callback_list.size(); i++)
               {
                  callback_list[i].execute("abc");
               }

               return true;
            }

            為簡(jiǎn)捷起見,與實(shí)例的驗(yàn)證(instance validation)相關(guān)的必要代碼沒(méi)有被包含進(jìn)來(lái),在實(shí)際的程序設(shè)計(jì)中,類實(shí)例的傳遞應(yīng)該基于這樣的結(jié)構(gòu):使用類似智能指針(smart pointer)的包裝類。STL(標(biāo)準(zhǔn)模板庫(kù))提供了兩個(gè)極好的選擇:aotu_ptr以及它的后繼:shared_ptr。Andrei Alexandrescu所著的《Modern C++ Design》一書也提供了一個(gè)面向策略設(shè)計(jì)(policy design oriented)的智能指針類。這三種方案中各有自己的優(yōu)缺點(diǎn),最終由用戶自己來(lái)決定究竟那一種最適合他們的需要。

            posted on 2011-01-25 15:07 老馬驛站 閱讀(1311) 評(píng)論(0)  編輯 收藏 引用 所屬分類: c++
            精品国产一区二区三区久久蜜臀| 久久经典免费视频| 久久人人爽人人人人爽AV| 一级做a爰片久久毛片人呢| 久久精品中文字幕无码绿巨人| 欧美久久久久久| 麻豆精品久久久久久久99蜜桃| 欧美精品一区二区久久| 国产精品伊人久久伊人电影| 成人精品一区二区久久久| 国产精品9999久久久久| 久久精品一区二区三区不卡| 99久久er这里只有精品18| 2021少妇久久久久久久久久| 久久综合综合久久97色| 精品99久久aaa一级毛片| 午夜视频久久久久一区 | 久久一区二区三区免费| 婷婷久久综合九色综合98| 亚洲国产精品久久久久| 免费精品久久久久久中文字幕 | 丁香五月综合久久激情| 久久久久久久国产免费看| 三级片免费观看久久| 久久综合亚洲色一区二区三区| 久久综合狠狠综合久久| 国产福利电影一区二区三区久久久久成人精品综合 | 欧美麻豆久久久久久中文| 亚洲精品国精品久久99热一| 韩国免费A级毛片久久| 亚洲国产成人久久综合碰碰动漫3d| 国产亚洲精久久久久久无码AV| 久久亚洲高清综合| 国产精品女同久久久久电影院| 国产午夜精品久久久久九九| 久久综合久久综合亚洲| 2022年国产精品久久久久| 波多野结衣久久| 91精品国产色综久久| 久久精品国产2020| 国产毛片久久久久久国产毛片|