c++之function和bind详解-SurfaceFlinger学习必备语法基础

背景

C++中的function和bind是为了更方便地进行函数对象的封装和调用而设计的,在SurfaceFlinger源码中也是有很多使用部分。
比如分析Vsync相关源码时候有相关回调时候

在这里插入图片描述可以看到这里的mRegistration就有个参数是 std::bind,怎么这里就可以进行回调呢?
所以基于以上背景就需要学习今天的function和bind的知识才可以很轻松的分析对。

function

文档描述:
在这里插入图片描述

总结概况:

function是一个通用的函数对象容器,可以存储任意可调用对象(函数、函数指针、成员函数、成员变量、lambda表达式,任何function对象,比如一个类,定义了operator()),并提供了一致的接口来调用这些对象。通过function,可以将一个函数或函数对象作为参数传递给其他函数或存储在容器中,大大提高了灵活性。

template <class Ret, class... Args> class function<Ret(Args...)>;

参数解释:

Ret:代表调用function的返回结果的类型

Args:代表是参数的类型。

demo展示:

1、function存储函数指针方式

#include <iostream>
#include <functional>

int fl(int a)
{
    std::cout << "a = " << a<< std::endl;
    return a*2;
}

int main()
{
    //直接可以接受函数指针的赋值
    std::function<int(int)> f = fl;
    int functionResult = f(1);
    std::cout<<"function result = "<<functionResult<<std::endl;
    int directResult   = fl(1);
    std::cout<<" fl result = "<<directResult<<std::endl; // 调用fl函数

    return 0;
}
结果如下:

在这里插入图片描述
明显可以看到这里使用function对象调用方式和直接调用方法的方式都是一样的,结果都是2

2、存储类对象
在这里插入图片描述

可以看到这里的Add类对象也是可以作为一个作为一个function对象,但是这里需要注意Add类一定要进行重载operator这个方法

3、存储成员方法
代码如下:
在这里插入图片描述可以看出这里可以直接边类的成员方法赋值给function,不过这里function的Args里面第一个参数必须要求传递类对象。
调用function时候第一个参数也是必须要是Add类的对象

4、lamada表达式情况

在这里插入图片描述可以看出lamada表达式也是可以直接赋值给function对象

5、类成员变量情况
在这里插入图片描述可以看到类成员也可以直接通过function方式获取得到正确数据。

bind

学习文档:
https://legacy.cplusplus.com/reference/functional/bind/?kw=bind
在这里插入图片描述

总结bind作用:

bind是将函数和其参数进行绑定的工具,可以将一个函数和部分参数绑定在一起,生成一个新的函数对象,这个新的函数对象可以像原函数一样进行调用,但会自动填充绑定的参数。

核心参数补充:
第一个参数 fn
一个function对象,方法指针,或者是类成员变量

第二个参数 args
所有参数的集合列表,要买具体的值,要么placeholders

返回值
就是一个function的对象,当调用时候调用的就是fn这个方法体和带上传递的参数

重点强调一下最后两个:

If fn is a pointer to member, the first argument expected by the returned function is an object of the class *fn is a member (or a reference to it, or a pointer to it).

大概意思是如果fn是一个类成员相关的,那么第一个参数就需要是这个类的引用或者指针。

demo代码:

// bind example
#include <iostream>     // std::cout
#include <functional>   // std::bind

// a function: (also works with function object: std::divides<double> my_divide;)
double my_divide (double x, double y) {return x/y;}

struct MyPair {
  double a,b;
  double multiply() {return a*b;}
};

int main () {
  using namespace std::placeholders;    // adds visibility of _1, _2, _3,...

  // binding functions:
  auto fn_five = std::bind (my_divide,10,2);               // returns 10/2
  std::cout << fn_five() << '\n';                          // 5

  auto fn_half = std::bind (my_divide,_1,2);               // returns x/2
  std::cout << fn_half(10) << '\n';                        // 5

  auto fn_invert = std::bind (my_divide,_2,_1);            // returns y/x
  std::cout << fn_invert(10,2) << '\n';                    // 0.2

  auto fn_rounding = std::bind<int> (my_divide,_1,_2);     // returns int(x/y)
  std::cout << fn_rounding(10,3) << '\n';                  // 3

  MyPair ten_two {10,2};

//这里fn就是类成员方法,第一个参数就要求是这个类的对象,不过这里用的是空缺std::placeholders _1
  // binding members:
  auto bound_member_fn = std::bind (&MyPair::multiply,_1); // returns x.multiply()
  //这里调用时候传递了真正的对象ten_two
  std::cout << bound_member_fn(ten_two) << '\n';           // 20
//这里fn就是类成员变量,第一个参数就要求是这个类的对象
  auto bound_member_data = std::bind (&MyPair::a,ten_two); // returns ten_two.a
  std::cout << bound_member_data() << '\n';                // 10

  return 0;
}

std::placeholders _1,_2…就代表预制第1,2、、、个参数,后续真正调用function对象时候再传递进去

实战使用结合

在这里插入图片描述可以看到这里的mRegistration构造方法第二个参数就是std::bind,即绑定方法,绑定是一个CallbackRepeater::callback的成员方法,而且有3个保留参数,即后续会传递进来的。bind后就变成了function类型对象。那么这里的Registration第二个构造参数是啥呢?

在这里插入图片描述这里的Callback实际就是地道的function对象

  using Callback =
            std::function<void(nsecs_t vsyncTime, nsecs_t targetWakeupTime, nsecs_t readyTime)>;

最后传递到了VSyncDispatchTimerQueueEntry中,在调用VSyncDispatchTimerQueueEntry的callback方法时候会调用上面的function类

在这里插入图片描述
本文章对应视频手把手教你学framework:
hal+perfetto+surfaceflinger
https://mp.weixin.qq.com/s/LbVLnu1udqExHVKxd74ILg
在这里插入图片描述

私聊作者+v(androidframework007)

七件套专题:在这里插入图片描述
点击这里 https://mp.weixin.qq.com/s/Qv8zjgQ0CkalKmvi8tMGaw

视频:https://www.bilibili.com/video/BV1wc41117L4/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值