函數綁定:
1.函數對象
(1.1)能夠被當做函數調用的不一定就是函數,它們也可能是:
A.存放函數入口地址的函數指針
B.實現了小括號運算符的類對象,亦稱仿函數
C.可被轉換為函數指針的類對象
(1.2)可調用對象,像函數指針,仿函數以及可被轉換為函數指針的類對象都被稱為可調用對象,而他們的類型就被稱為可調用類型
(1.3)函數對象,函數對象實際上是一個function類模板的實例化對象,其中封裝了以上三種可調用對象的任何一種,
對函數對象的調用,實際就是對被其封裝的可調用對象的調用
#include <iostream> #include <functional> using namespace std; int fun(int x, int y) { cout << __FUNCTION__ << endl; return x + y; } class Foo { public: Foo(void) {} Foo(int x, int y) :m_x(x), m_y(y) {} int operator()(int x, int y)const { cout << __FUNCTION__ << "1" << endl; return x + y; } int operator()(void)const { cout << __FUNCTION__ << "2" << endl; return m_x + m_y; } private: int m_x, m_y; }; class Bar { //C++11通過using關鍵字給函數指針起別名 using mfun_t = int(*)(int, int); public: //operator隱式類型轉換,函數指針也是一種類型 operator mfun_t(void)const { return mfun; } private: static int mfun(int x, int y) { cout << __FUNCTION__ << endl; return x + y; } }; int add(int x, int y, function<int(int, int)>f) { return f(x, y); } int main() { //函數不是可調用的對象 cout << fun(123, 456) << endl; //函數指針形式的可調用對象 int(*pfunc)(int, int) = fun; cout << pfunc(123, 456) << endl; //仿函數形式的可調用對象 Foo foo1; cout << foo1(123, 456) << endl; //cout << foo1.operator()(123,456) << endl; Foo foo2(123, 456); cout << foo2() << endl; //可被轉換為函數指針的類對象形式的可調用對象 Bar bar; cout << bar(123, 456) << endl; //function時一個模板,function<int(int,int)>表示接受兩個int,返回一個int的可調用對象 function<int(int, int)> f1 = pfunc; cout << f1(123, 456) << endl; function<int(int, int)> f2 = foo1; cout << f2(123, 456) << endl; function<int(int, int)> f3 = bar; cout << f3(123, 456) << endl; cout << add(111, 222, pfunc) << endl; cout << add(111, 222, foo1) << endl; cout << add(111, 222, bar) << endl; return 0; }
2.函數綁定器
(2.1)函數綁定器可以將一個可調用對象和期望傳遞給該可調用對象的全部或者部分參數綁定為一個函數對象,
對該函數對象的調用就是在調用被其綁定的可調用對象。
函數對象 bind(可調用對象,期望參數表)
期望參數表可包含期望傳遞給可調用對象的0到多個參數
函數對象 <==> 可調用對象(期望參數表)
(2.2)placeholders::_n是一個占位符,其值將由傳遞給函數對象的第n個(從1開始算)參數取代。
#include <iostream> #include <functional> using namespace std; int fun(int x, int y) { cout << __FUNCTION__ << endl; return x + y; } class Foo { public: //重載()運算符 int operator()(int x, int y)const { cout << __FUNCTION__ << endl; return x + y; } }; class Bind { public: Bind(int(*pfunc)(int, int), int x, int y) :m_pfunc(pfunc), m_x(x), m_y(y) {} //重載()運算符 int operator()(void)const { return m_pfunc(m_x, m_y); } private: int(*m_pfunc)(int, int); int m_x; int m_y; }; Bind myBind(int(*pfun)(int, int), int x, int y) { return Bind(pfun, x, y); } int main() { function<int(void)> f1 = bind(fun, 123, 456); cout << f1() << endl; cout << fun(123, 456) << endl; Bind f2 = myBind(fun, 123, 456); cout << f2() << endl; //placeholders定義在std命名空間中 function<int(int)> f3 = bind(fun, 123, placeholders::_1); cout << f3(456) << endl; //function<int(int,int)> f4 = bind(fun, placeholders::_1,placeholders::_2); auto f4 = bind(fun, placeholders::_1, placeholders::_2); cout << f4(123, 456) << endl; auto f5 = bind(fun, placeholders::_5, placeholders::_3); cout << f5(1, 2, 3, 4, 5, 6, 7, 8, 9) << endl; //cout<<f5(5,3)<<endl; auto f6 = bind(Foo(), 111, 222); cout << f6() << endl; //cout<<Foo()(111,222)<<endl; using placeholders::_1; using placeholders::_2; auto f7 = bind(Foo(), _1, _2); cout << f7(444, 555) << endl; return 0; }
3.無論類的普通成員函數還是靜態成員函數,都可以通過bind與其參數一起綁定為函數對象,
但是要注意作為類的普通成員函數需要連同傳遞給它的this指針一起綁定。
#include <iostream> #include <vector> #include <algorithm> #include <functional> using namespace std; bool IsJige(int score) { return score >= 60; } bool Compare(int num) { return num > 30; } void test() { vector<int> scores{ 60, 40, 50, 30, 80, 88, 85, 95, 10, 55,60 }; //count函數返回元素值為target的元素個數,int num=count(vector1.begin(),vector2.begin(),target),注意不是vector的類函數 int num = count(scores.begin(), scores.end(), 60); cout << num << endl;//2 num = count(scores.begin(), scores.end(), 40); cout << num << endl;//1 //count_if函數:返回符合一定條件的元素個數。compare()函數是自定義的,返回值是true就是表示符合要求 vector<int> vi = { 10,20,30,40,50,60 }; //返回大於30的個數 num = count_if(vi.begin(),vi.end(),Compare); cout << num << endl;//3 } int main() { test(); vector<int> scores{ 70, 40, 50, 30, 80, 88, 85, 95, 10, 55,60 }; int jige = 0; for (auto score : scores) if (score >= 60) ++jige; cout << "及格:" << jige << endl; //count函數和count_if函數見test函數 cout << "及格:" << count_if(scores.begin(), scores.end(), IsJige) << endl; //less_equal返回左邊參數是否小於等於右邊參數 cout << boolalpha << less_equal<int>()(60, 60) << endl;//true cout << less_equal<int>()(60, 80) << endl;//true cout << less_equal<int>()(60, 30) << endl;//false //less返回左邊參數是否小於右邊參數 cout << less<int>()(60, 60) << endl; using placeholders::_1; cout << "及格:" << count_if(scores.begin(), scores.end(), bind(less_equal<int>(), 60, _1)); cout << "不及格:" << count_if(scores.begin(), scores.end(), bind(less<int>(), _1, 60)); return 0; }