C++11系列學習之可調用對象包裝器和綁定器
舊標準的缺陷
學習新標準的語法之前,先來聊聊舊標準存在的缺陷,這樣就可以理解為什么要在C++11中存在std::funtion
和std::bind
了,這就是所謂——知其然,并知其所以然
繁雜的調用對象
C++中可以調用的對象有很多,包括但不限于以下:
- 函數指針
- 仿函數(重載了"( )" 運算符)
- 可被轉換為函數指針的類對象
- 類成員函數
問題浮出水面
這些調用對象在使用的時候具有比較統一的時候,但是定義的方式卻是五花八門。因此,C++11中為了改善這個問題,提供了std::function
和std::bind
來解決
std::function
std::function
是可調用對象的包裝器,本質上是一個類模板,可容納除了類成員(函數)指針之外的所有可調用對象
小試牛刀
#include<iostream> #include<functional> class A { std::function<void()> callback_; public: A(const std::function<void()>& f) : callback_(f){} void notify(void){ callback_(); //調用這個回調對象 } }; class Foo{ public: void operator()(void){ std::cout << __FUNCTION__ << std::endl; } }; int main(void) { Foo foo; A aa(foo); aa.notify(); //調用這個回調 return 0; } //輸出 //operator()
std::function因為有著保存函數并可以延遲執(zhí)行的特性,因此非常適合作為回調函數來使用
std::bind
std::bind
用來將可調用對象與其參數一起進行綁定,綁定后的結果可以使用std::function進行保存,并延遲調用。
作用
- 將可調用對象與其參數一起綁定成一個仿函數
- 將N元可調用對象轉換成一元或N-1元可調用對象,即只綁定部分參數
占位符
std::bind
可以將函數及其參數進行綁定,那么參數的位置與傳入的位置相關,因此有了占位符的概念,例如std::placeholders::_1
是第一個參數的占位符,當函數傳入第一個參數的時候,就會把其進行替換,同理std::palceholders::_2
是第二個占位符。
#include<iostream> #include<functional> void output(int x, int y){ std::cout << x << " " << y << std::endl; } int main(){ std::bind(output, 1, 2)(); //輸出:1 2 std::bind(output, std::placeholders::_1)(1); //輸出:1 std::bind(output, 2, std::placeholders::_2)(1,2); //輸出:2 2 std::bind(output, std::placeholders::_2, std::placeholders::_1)(1, 2); //輸出:2 1 }
高級用法
可以使用std::bind進行多個函數的組合,例如找出集合中大于5小于10的元素個數:
#include<iostream> #include<functional> using std::placeholders::_1; auto f = std::bind(std::logical_and<bool>(), std::bind(std::greater<int>(), _1, 5),std::bind(std::less_equal<int>(), _1, 10)); //將兩個函數參數綁定并進行組合 int count = std::count_if(coll.begin(), coll.end(), f); //使用
配合使用
std::bind
和std::function
配合使用非常的強大
#include<iostream> #include<funcational> class A{ public: int i_ = 0; void output(int x, int y){ std:cout << x << " " << y << std::endl; } }; int main(void){ A a; std::function<void(int, int)> fr = std::bind(&A::output, &a, std::placeholders::_1,std::palceholders::_2); //注意 fr(1, 2); //輸出:1 2 std::function<int&(void)> fr_i = std::bind(&A::i, &a); fr_i() = 123; std::cout << a.i_ << std::endl; //輸出:123 }
可以看到上面std::bind在綁定類的成員函數的時候,需要把&a也傳進去,這是因為成員函數編譯器在使用的時候會自動傳入一個this指針,所以我們綁定的時候需要額外傳一個對象的地址
到此這篇關于C++11系列學習之可調用對象包裝器和綁定器的文章就介紹到這了,更多相關C++11包裝器和綁定器內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Visual Studio 2019 DLL動態(tài)庫連接實例(圖文教程)
這篇文章主要介紹了Visual Studio 2019 DLL動態(tài)庫連接實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-03-03