muduo庫中的核心:std::bind和std::function
阿新 • • 發佈:2018-06-16
muduo main ons 源碼 綁定 func 靜態成員 con 函數
最近在讀完陳碩大牛的《Linux多線程服務端編程》以及muduo源碼後,對其中的一些實現細節有著十分深刻的印象,尤其是使用std::bind和std::function的回調技術。可以說,這兩個大殺器簡直就是現代C++的“任督二脈”,甚至可以解決繼承時的虛函數指代不清的問題。在此詳細敘述使用std::bind和std::function在C++對象之間的用法,用以配合解決事件驅動的編程模型。筆者才疏學淺,如果解釋的不正確希望朋友們不吝賜教。
下面的所有討論基於對象。
std::bind和std::function的基礎用法
#include<iostream> #include<functional> typedef std::function<void()> Functor; class Blas { public: void add(int a,int b) { std::cout << a+b << std::endl; } static void addStatic(int a,int b) { std::cout << a+b << std::endl; } }; int main(int argc,char** argv) { Blas blas; //使用bind綁定類靜態成員函數 Functor functor(std::bind(&Blas::addStatic,1,2)); //使用bind綁定類的chengyuan函數 Functor functor(std::bind(&Blas::add,blas,1,2)); functor(); return 0; }
上述代碼中的區別是:如果不是類的靜態成員函數,需要在參數綁定時,往綁定的參數列表中加入使用的對象。
使用std::function和std::bind實現回調功能
#include<iostream> #include<functional> typedef std::function<void()> Functor; class Blas { public: void setCallBack(const Functor& cb) {functor = cb;}; void printFunctor() {functor();}; private: Functor functor; }; class Atlas { public: Atlas(int x_) : x(x_) { //使用當前類的靜態成員函數 blas.setCallBack(std::bind(&addStatic,x,2)); //使用當前類的非靜態成員函數 blas.setCallBack(std::bind(&Atlas::add,this,x,2)); } void print() { blas.printFunctor(); } private: void add(int a,int b) { std::cout << a+b << std::endl; } static void addStatic(int a,int b) { std::cout << a+b << std::endl; } Blas blas; int x; }; int main(int argc,char** argv) { Atlas atlas(5); atlas.print(); return 0; }
在以上代碼中的
void add();
void addStatic();
兩個函數在Atlas類中,並且可以自由操作Atlas的數據成員。盡管是將add()系列的函數封裝成函數對象傳入Blas中,並且在Blas類中調用,但是它們仍然具有操作Atlas數據成員的功能,在兩個類之間形成了弱的耦合作用。但是如果要在兩個類之間形成弱的耦合作用,必須在使用std::bind()
封裝時,向其中傳入this指針:
std::bind(&Atlas::add,this,1,2);
也就是說,要在兩個類之間形成耦合作用,要使用非靜態的成員函數(私有和公有都可以)。代碼如下:
#include<iostream> #include<functional> typedef std::function<void()> Functor; class Blas { public: void setCallBack(const Functor& cb) {functor = cb;}; void printFunctor() {functor();}; private: Functor functor; }; class Atlas { public: Atlas(int x_,int y_) : x(x_),y(y_) { //使用當前類的非靜態成員函數 blas.setCallBack(std::bind(&Atlas::add,this,x,2)); } void print() { blas.printFunctor(); } private: void add(int a,int b) { std::cout << y << std::endl; std::cout << a+b << std::endl; } Blas blas; int x,y; }; int main(int argc,char** argv) { Atlas atlas(5,10); atlas.print(); return 0; }
這樣,便可以Atlas便可以在Blas類中註冊一些函數對象,這些函數對象在處理Blas數據的同時(在std::bind中預留位置傳入Blas的參數),還可以回帶處理Atlas的數據,形成回調作用。代碼如下:
#include<iostream>
#include<functional>
typedef std::function<void(int,int)> Functor;
class Blas
{
public:
void setCallBack(const Functor& cb)
{functor = cb;};
void printFunctor()
{functor(x,y);};
private:
int x = 10;
int y = 10;
Functor functor;
};
class Atlas
{
public:
Atlas(int x_,int y_) : x(x_),y(y_)
{
//使用當前類的非靜態成員函數
blas.setCallBack(std::bind(&Atlas::add,this,std::placeholders::_1,std::placeholders::_2));
}
void print()
{
blas.printFunctor();
}
void printFunctor()
{functor(x,y);};
private:
int x = 10;
int y = 1:;
Functor functor;
};
class Atlas
{
public:
Atlas(int x_,int y_) : x(x_),y(y_)
{
//使用當前類的非靜態成員函數
blas.setCallBack(std::bind(&Atlas::add,this,std::placeholders::_1,std::placeholders::_2));
}
void print()
{
blas.printFunctor();
}
private:
void add(int a,int b)
{
std::cout << y << std::endl;
std::cout << a+b << std::endl;
}
Blas blas;
int x,y;
};
int main(int argc,char** argv)
{
Atlas atlas(5,10);
atlas.print();
return 0;
}
muduo庫中的核心:std::bind和std::function