0909,bind函数,std::function & std::bind的回调函数实现

  1. remove if
  2. bind1st,bind2nd
  3. bind(普通,成员)
  4. copy
  5. 引用折叠
  6. 函数指针/指针函数
  7. 回调函数-延迟调用的思想
  8. 占位符
  9. function
  10. function+lambda
  11. 对象+回调函数对象
  12. bind+function+mem fn
  13. std::cref占位遍历

01_bind.cc

#include <iostream>
#include <functional>
using std::cout;
using std::endl;
using std::bind;
using std::function;

int add0(int a,int b){
    cout<<"add(0)(int int )"<<endl;
    return a+b;
}
int add1(int a,int b,int c){
    cout<<"add(1)(int int int)"<<endl;
    return a+b+c;
}

class Exemple{
public:
    int add2(int a,int b){
        cout<<"Exemple::add(2)(int int )"<<endl;
        return a+b;
    }
    int _data=100;
};

void test(){
    //函数的形态(类型,标签):函数的返回类型+参数列表
    //(参数的个数,顺序,类型)

    //add0:int (int,int)
    //f0:int()
    auto f0=bind(&add0,1,2);
    cout<<f0()<<endl<<endl;

//----------//
//引用折叠
//& &&-->  &
//& & -->  &
//&& & ->  &
//&& &&->  &&

    //add1:int (int,int,int)
    //f1:int()
    auto f1=bind(add1,3,4,6);
    cout<<f1()<<endl<<endl;

    //add2:int (Exemple*,int,int)
    //f2:int()
    Exemple ex;
    auto f2=bind(&Exemple::add2,&ex,10,20);
    cout<<f2()<<endl<<endl;
    /* Exemple::add2(10,20); */
    //成员函数有隐藏参数this指针

    auto f4=bind(&Exemple::add2,ex,10,20);
    cout<<f4()<<endl<<endl;
    //如果ex已经销毁,&ex就会对空指针进行解引用
    //传对象则没有影响(copy了一份副本,生命周期和bind一致)
    //传地址(一个地址的开销)   传对象(一个对象的开销)


    //占位符
    //add1:int (int,int,int)
    //f5:  int(int)
    using namespace std::placeholders;
    auto f5=bind(add1,100,_1,20);
    cout<<f5(400,500,500)<<endl<<endl;
    /* f1=bind(add1,100,_1,20); */
    

    function<int()> f3=bind(&Exemple::_data,&ex);
    cout<<f3()<<endl<<endl;
    //数据成员(将数据成员的名字看成函数名字
    //数据成员的类型看成函数的返回类型

}






void func(int a1,int a2,int a3,const int &a4,int a5){
    cout<<"a1--"<<a1
        <<"\ta2--"<<a2
        <<"\ta3--"<<a3
        <<"\ta4--"<<a4
        <<"\ta5--"<<a5<<endl;
}

void test1(){
    //占位符整体,代表的函数的形参位置
    //占位符种的数字,代表的是实参的位置
    //std::cref=const reference,引用的包装器
    int num=100;
    using namespace std::placeholders;
    auto f=bind(func,10,_1,_2,std::cref(num),num);
                              //100->a4,a5
                              //默认的传递方式是值传递
    num=200;
    f(1,20,300,4000,5000);
    //a1--10	a2--1	a3--20	a4--100	a5--100
    //10->a1   1/_1->a2   20/_2->a3,剩下的扔掉
    f(800,200);
}



int main(void)
{
    test();
    test1();
    return 0;
}

02_funcPoint.cc

#include <iostream>
using std::cout;
using std::endl;

int func1(){
    return 10;
}
int func2(){
    return 20;
}
int add0(int a,int b){
    cout<<"add(0)(int int )"<<endl;
    return a+b;
}

//指针函数,函数的返回类型是指针
//int* re_arr(){
//  reuturn int*=new int[5]();
//}
//<深入理解C指针>

void test(){
    typedef int (*pFunc1)();//函数指针
                            //C写法
    /* typedef int(*)() pfunc;//error */
    using pfunc=int(*)();//取别名的另一种方式
                         //C++写法

    //回调函数--将函数作为参数传递(延迟调用的思想??不懂)

    pFunc1 f=func1;//注册回调函数
    pfunc f1=func1;
    cout<<f()<<endl;//回调函数的执行
    cout<<f1()<<endl;

    f=func2;
    f1=func2;
    cout<<f()<<endl;
    cout<<f1()<<endl;

    /* f=add; */
    //函数形态不一致
}

int main(void)
{
    test();
    return 0;
}

03_lambda.cc

#include <iostream>
#include <functional>
#include <vector>
#include <string>
using std::cout;
using std::endl;
using std::vector;
using std::string;
using std::function;

void test(){

    int num=10;
    int age=20;

    //fuction,类模板,封装一切可以调用的对象
    //普通/成员函数,函数对象,lambda表达式

    //lambda 的函数形态:void(int)
    function<void(int)> f=[&age,num](int value){
        /* auto f=[&age,num](int value){ */
        ++age;
        ++value;
        cout<<"age--"<<age<<"\tnum--"
            <<num<<"\tvalue--"<<value<<endl;
    };

    f(100);
    f(200);

}

vector<function<void(const string &)>> vec;
void test1(){


    int num=100;
    string name("xixi");
    /* function<void(const string &)> f= */
    /*     [&num,&name](const string & val)->void{ */
    /*         cout<<num<<"--"<<name<<"--"<<val<<endl; */
    /*     }; */
    //return type可以省略

    /* vec.push_back([&num,&name](const string &val){ */
    vec.push_back([num,name](const string &val){
                  cout<<num<<"--"<<name<<"--"<<val<<endl;
                  });
    //捕获局部变量的引用,药保证其不被销毁
    for(auto ele:vec){
        ele("wuhan");
    }
}
void test2(){
    for(auto ele:vec){
        ele("wuhan");
    }
}

int main(void)
{
    test();
    test1();
    test2();
    return 0;
}

04_bind1st_bind2nd.cc

#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
using std::cout;
using std::endl;
using std::bind;
using std::vector;


template <typename Container>
void display( Container & con){
    for(auto &ele: con){
        cout<<ele<<" ";
    }
    cout<<endl;
}


void test(){
    vector<int> vec{1,5,3,6,2,7,23,3,6};
    display(vec);
    //delete all val>4
    auto it=remove_if(vec.begin(),vec.end(),[](int & value)->bool{
                      return value>4;
                      });
    display(vec);
    //pread pwrite 满足一元谓词->删除,read++
    //不满足,swap *pread & *pwrite,pread++,return ++pwrite
    vec.erase(it,vec.end());
    display(vec);
}
void test1(){
    vector<int> vec{1,5,3,6,2,7,23,3,6};
    display(vec);
    //less(val1,val2){return val1<val2;}
    /* auto it=remove_if(vec.begin(),vec.end(), */
    /*                   bind1st(std::less<int>(),4)); */
    auto it=remove_if(vec.begin(),vec.end(),
                      bind2nd(std::greater<int>(),4));
    display(vec);
    vec.erase(it,vec.end());
    display(vec);
}



int main(void)
{
    test();
    test1();
    return 0;
}

05_bind_figure.cc

#include <iostream>
#include <functional>
#include <math.h>
using std::cout;
using std::endl;
using std::bind;
using std::function;

//面向对象:继承+虚函数(纯虚函数)
//基于对象:std::bind+std::function(更加灵活
//
//总结:在C语言中,解决回调函数的注册与执行 --> 函数指针
//C++:std::bind + std::function
//-------------------------------------------------//
class Figure
{
public:
    //纯虚函数
    /* virtual void display() const = 0; */
    /* virtual double area() const = 0; */
    using DisplayCallBack=function<void()>;
    using AreaCallBack=function<double()>;

    //bind(``````)是右值
    /* void setDisplayC(const DisplayCallBack & dc){ */
    //函数注册到成员函数
    void setDisplayC(const DisplayCallBack && dc){
        _display_callback=std::move(dc);
    }
    void setArea(const AreaCallBack && dc){
        _area_callback=std::move(dc);
    }
    //执行注册的函数
    void handleDisplayC()const{
        if(_display_callback){
            _display_callback();
        }//nullptr
    }
    double handleAreaC()const{
        if(_area_callback){
            return _area_callback();
        }
        return 0.0;
    }
public:
    DisplayCallBack _display_callback;
    AreaCallBack _area_callback;
};

//-------------------------------------------------//
class Rectangle
: public Figure
{
public:
    Rectangle(double length = 0, double width = 0)
    : _length(length)
    , _width(width){
        cout << "Rectangle(double = 0, double = 0)" << endl;
    }

    void displsy_r(int val) const {
        cout << "Rectangle";
    }

    double area_r() const {
        return _length * _width;
    }

    ~Rectangle(){}
private:
    double _length;
    double _width;
};

//-------------------------------------------------//
class Circle
: public Figure
{
public:
    Circle(double radius = 0)
    : _radius(radius){
        cout << "Circle(double = 0)" << endl;
    }

    void display_c() const {
        cout << "Circle";
    }

    double area_c() const {
        return 3.14 * _radius *_radius;;
    }
    ~Circle(){}
private:
    double _radius;
};


//-------------------------------------------------//
class Triangle
: public Figure
{
public:
    Triangle(double a = 0, double b = 0, double c = 0)
    : _a(a)
    , _b(b)
    , _c(c){
        cout << "Triangle(double = 0, double = 0, double = 0)" << endl;
    }

    void display_t() const {
        cout << "Triangle";
    }

    double area_t() const {
        //海伦公式
        double tmp = (_a + _b + _c)/2;
        return sqrt(tmp * (tmp - _a) * (tmp - _b) * (tmp - _c));
    }

    ~Triangle(){}
private:
    double _a;
    double _b;
    double _c;
};


//-------------------------------------------------//
//-------------------------------------------------//
/* void func(const Figure &fig){ */
/*     fig.display(); */
/*     cout << "的面积 : " << fig.area() << endl; */
/* } */

void func(const Figure  &fig){
    fig.handleDisplayC();
    cout<<"area: "<<fig.handleAreaC()<<endl;
}

//-------------------------------------------------//
//-------------------------------------------------//
void test(){
    Rectangle r(10, 20);
    Circle c(10);
    Circle c1;
    Triangle t(3, 4, 5);
    cout<<endl;

    Figure fig;
    /* &bind(&Rectangle::displsy_r(),&r,10); */
    fig.setDisplayC(bind(&Rectangle::displsy_r,&r,10));
    fig.setArea(bind(&Rectangle::area_r,&r));
    func(fig);

    fig.setDisplayC(bind(&Circle::display_c,&c));
    fig.setArea(bind(&Circle::area_c,&c));
    func(fig);
    fig.setDisplayC(bind(&Circle::display_c,&c1));
    fig.setArea(bind(&Circle::area_c,&c1));
    func(fig);
    
    fig.setDisplayC(bind(&Triangle::display_t,&t));
    fig.setArea(bind(&Triangle::area_t,&t));
    func(fig);
}



int main(void)
{
    test();
    return 0;
}

06_mem_fn.cc

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
using std::cout;
using std::endl;
using std::for_each;
using std::mem_fn;
using std::ostream;
using std::vector;
using std::function;

class Number
{
public:
    Number(size_t data=0)
        :_data(data)
    {}
    ~Number(){}
    bool isEven()const{
        return _data%2==0;
    }
    bool isPrime()const{
        if(_data==1){
            return false;//1不是素数
        }
        for(size_t i=2;i<=_data/2;++i){
            if(_data%i==0){return false;}
        }
        return true;
    }
    void print(){
        cout<<_data<<" ";
    }
    friend ostream & operator<<(ostream & os,const Number & n);
private:
    size_t _data;
};
ostream & operator<<(ostream & os,const Number & n){
    os<<n._data<<" ";
    return os;
}


void test(){
    vector<Number> vec;
    for(size_t i=1;i!=30;++i){
        vec.push_back(Number(i));
    }
    //mem_fn用于将成员函数指针封装成一个函数对象
    //使得可以像普通函数一样调用
    /* for_each(vec.begin(),vec.end(),mem_fn(&Number::operator=)); */
    for_each(vec.begin(),vec.end(),mem_fn(&Number::print));
    cout<<endl;

    //删除偶数
    auto it=remove_if(vec.begin(),vec.end(),mem_fn(&Number::isEven));
    vec.erase(it,vec.end());
    for_each(vec.begin(),vec.end(),mem_fn(&Number::print));
    cout<<endl;

    //删除质数
    it=remove_if(vec.begin(),vec.end(),mem_fn(&Number::isPrime));
    vec.erase(it,vec.end());
    for_each(vec.begin(),vec.end(),mem_fn(&Number::print));
    cout<<endl;


//--------------------------------------------------//
    Number n(10);
    for_each(vec.begin(),vec.end(),std::bind(&Number::print,&n));
    /* for_each(vec.begin(),vec.end(),std::bind(&Number::print,n)); */
    cout<<endl;

    using namespace std::placeholders;

    /* function<void(Number)> f=bind(&Number::print,_1); */
    //成员函数,类型不正确??

    function<void(Number&)> f=bind(&Number::print,_1);
/* 创建一个 std::function<void(Number&)> 对象 f,它将 
 * Number 类的iprint 成员函数与占位符 _1 绑。 */
/* 这里 _1 表示在 for_each 中调用 f 时,将传递的每个元素
 * 作为 print 的参数,即每个 Number 对象的引用。 */

    for_each(vec.begin(),vec.end(),f);
    cout<<endl;
    for_each(vec.begin(),vec.end(),bind(&Number::print,_1));
    cout<<endl;

}

int main(void)
{
    test();
    return 0;
}

作业:

01 什么是回调函数,注册回调函数,执行回调函数?(掌握std::bind用法,非常重要)

std::bind的实现原理阅读材料

http://www.cnblogs.com/xusd-null/p/3698969.html

01_bind.cc 

02 std::bind可以绑定什么?bing绑定成员函数的传参有什么区别?

1,普通函数

2,成员函数(普通成员函数还需要传递函数对象,静态成员函数不需要

3,数据成员(名字看作函数名字,类型看作返回类型

4,lambda表达式

03 使用std::bind与std::function(基于对象的形式)实现上课所讲的Figure的例子的代码?

05_bind_figure.cc

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值