程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> [Boost基礎]函數與回調——bind綁定

[Boost基礎]函數與回調——bind綁定

編輯:C++入門知識

[cpp]  #pragma  once   #include <boost/bind.hpp>    #include <string>   #include <iostream>   #include <conio.h>    #include <vector>   #include <algorithm>   using namespace std;    using namespace boost;    //bind是C++98標准庫中函數適配器bind1st、bind2nd的泛化和增強,可以適配任意的可調用對象,包括函數,函數指針,函數引用,成員函數指針和函數對象。bind遠遠的超越了STL中的函數綁定其(bind1st/bind2nd),可以綁定最多9個函數參數,而且對綁定對象的要求很低,可以在沒有result_type內部類型定義的情況下完成對函數對象的綁定。bind庫很好的增強了標准庫的功能。   //綁定普通函數(函數,函數指針)   int f(int a,int b){return a+b;}//二元函數   int g(int a,int b,int c){return a+b*c;}//三元函數   void test1()   {              //綁定表達式沒有使用占位符       cout<<bind(f,1,2)()<<endl;//3 bind(f,1,2)返回一無參調用的函數對象,等價於f(1,2)       cout<<bind(g,1,2,3)()<<endl;//7 同上       cout<<f(1,2)<<" "<<g(1,2,3)<<endl;//3 7          //使用占位符       int x=0,y=1,z=2;        cout<<bind(f,_1,9)(x)<<endl;//9 ==>>f(x,9)       cout<<bind(f,_1,_2)(x,y)<<endl;//1 ==>>f(x,y)       cout<<bind(f,_2,_1)(x,y)<<endl;//1 ==>>f(y,x)       cout<<bind(f,_1,_1)(x,y)<<endl;//0 ==>>f(x,x);y參數被忽略了       cout<<bind(g,_1,8,_2)(x,y)<<endl;//8 ==>>g(x,8,y)       cout<<bind(g,_3,_2,_2)(x,y,z)<<endl;//3 ==>>g(z,y,y);x參數被忽略了       //必須在綁定表達式中提供函數要求的所有參數,無論是真實參數還是占位符均可以。但不能使用超過函數參數數量的占位符,eg:在綁定f是不能使用_3;在綁定g是不能使用_4;也不能寫bind(f,_1,_2,_2)這樣的形式,否則會導致編譯錯誤     }     //綁定函數指針 用法同上,可以還有占位符,也可以不使用占位符   typedef int (*f_type)(int,int);//函數指針定義   typedef int(*g_type)(int,int,int);//函數指針定義    void test2()   {          f_type pf=f;       g_type pg=g;       int x=1,y=2,z=3;       cout<<bind(pf,_1,9)(x)<<endl;//10  ==>>(*pf)(x,9)       cout<<bind(pg,_3,_2,_2)(x,y,z)<<endl;//7 ==>>(*pg)(z,y,y)   }    //綁定成員函數   void test3()   {  //類的成員函數不同於普通函數,因為成員函數指針不能直接調用opreator(),它必須被綁定到一個對象或者指針上,然後才能得到this指針進而調用成員函數。因此bind需要犧牲一個占位符的位置(意味著使用成員函數是只能最多綁定8個參數),要求用戶提供一個類的實例,引用或者指針,通過對象最為第一個參數來調用成員函數。       struct demo//使用struct僅僅是為了方便,不必寫出public       {            int f(int a,int b){return a+b;}       };       demo a,&ra=a,*p=&a;//類的實例對象,引用,指針       cout<<bind(&demo::f,a,_1,20)(10)<<endl;//30 ==>>a.f(10,20)       cout<<bind(&demo::f,ra,_2,_1)(10,20)<<endl;//30 ==>>ra.f(20,10)       cout<<bind(&demo::f,p,_1,_2)(10,20)<<endl;//30 ==>p->f(10,20)       //注意:我們必須在成員函數前加上取地址操作符&,表明這是一個成員函數指針,否則會無法通過編譯,這是與綁定函數的一個小小的不同。          //bind能夠綁定成員函數,這是個非常有用的功能,它可以代替標准庫中令人迷惑的mem_fun和mem_fun_ref綁定器,用來配合標准算法操作容器中的對象。下面試使用bind搭配標准算法for_each用來調用容器中所有對象的print()函數:       struct point       {           int x,y;           point(int a=0,int b=0):x(a),y(b){}           void print(){cout<<"("<<x<<","<<y<<") ";}       };       vector<point>v(2,3);       for_each(v.begin(),v.end(),bind(&point::print,_1));       //(3,0) (3,0)       //bind同樣支持綁定虛擬成員函數,用法與非虛擬成員函數相同,虛函數的行為將有實際調用發生時的實例來決定。   }   //綁定函數對象   void test4()   {         //如果函數對象有內部類型定義result_type,那麼bind可以自動推導出返回值的類型,用法與綁定普通函數一樣。但如果函數對象沒有定義result_type,則需要在綁定形式上做一點改動,用模板參數指明返回類型,eg bind<result_type>(Functor,...)          //標准庫和boost庫中大部分函數對象都具有result_type定義,因此不需要特別的形式就可以直接使用bind       int x=5,y=2;       //cout<<bind(greater<int>(),_1,10)(x)<<endl;//0 檢查x>10       //cout<<bind(plus<int>(),_1,_2)(x,y)<<endl;//7  執行x+y       //cout<<bind(modulus<int>(),_1,3)(x)<<endl;//2  執行 x%3       //上面三行在vs2010中沒問題,但在vs2008中有問題          //對於自定義函數對象,如果沒有result_type類型定義,eg       struct f       {           int operator()(int a,int b)           { return a+b;}       };       cout<<bind<int>(f(),_1,_2)(x,y)<<endl;//7       //這種寫法多少會有些不方便,因此,在編寫自己的函數對象是,最好遵循規范為它們增加內部typedef result_type,這樣將使函數對象與許多其他標准庫和boost庫組件良好配合工作。   }   //綁定成員變量   void test5()   {       struct point       {           int x,y;           point(int a=0,int b=0):x(a),y(b){}           void print(){cout<<"("<<x<<","<<y<<") ";}       };       vector<point>v(2,3);       vector<int>v2(2);       transform(v.begin(),v.end(),v2.begin(),bind(&point::x,_1));       }   //使用ref庫   void test6()   {//bind采用拷貝的方式存儲綁定對象和參數,這意味著綁定表達式中的每個變量都會有一份拷貝,如果函數對象或值參數很大,拷貝代價很高,或者無法拷貝,那麼bind的使用就會受到限制。因此bind庫可以搭配ref庫使用,ref庫包裝了對象的引用,可以讓bind存儲對象引用實例,從而降低了拷貝的代價。(必須包裝引用的對象存在,其沒有銷毀)          int x=10;       cout<<bind(g,_1,cref(x),ref(x))(10)<<endl;//110    }   void test(char t)   {       cout<<"press key====="<<t<<endl;       switch (t)       {        case '1':test1();break;       case '2':test2();break;       case '3':test3();break;       case '4':test4();break;       case '5':test5();break;       case '6':test6();break;       case 27:       case 'q':exit(0);break;       default: cout<<"default "<<t<<endl;break;       }   }   int main()   {       while(1)       {           test(getch());       }        return 0;   }  

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved