2 bind用法详解

这一篇讲讲bind,话说bind-function技术有一段时间很潮啊,扬言分分钟灭掉面向对象编程妥妥的,让四人帮的设计模式再也无用武之地,其实听到这个消息我非常的郁闷,因为设计模式我还没有怎么学会,就眼看要被淘汰了啊。所以我们现在看看bind-function的用法吧,我用的是C++11中,std的bind而不是boost的bind。
一,可调用对象
C++中有一个概念叫做可调用对象,让截然不同的概念,加个括号,填写参数就能够统一使用,真是让人震惊了。比如在加个括号,填写参数后,
1,函数指针,相当调用了这个函数;
2,函数对象,相当调用该对象的.operator(params)方法;
3,成员函数指针,这个在前面加了调用它的对象后,就变为这个对象调用该方法。
二,利用std::funciton模板对上面三个内容进行接收
.h
class BindDemo
{
public:
BindDemo();
void useFunction();
static double aMemberFunc(double param);
int operator()(int param);
};
inline double aFreeFunc(double param);
.cpp
#include "binddemo.h"
#include <functional>
#include <iostream>
BindDemo::BindDemo()
{
useFunction();
}

void BindDemo::useFunction()
{
//1
std::function<double(double)> fr1 = aFreeFunc;
std::cout<<fr1(5)<<std::endl;

//2
std::function<double(double)> fr2 = BindDemo::aMemberFunc;
std::cout<<fr2(6)<<std::endl;

//3
std::function<double(double)> fr3 = *this;
std::cout<<fr3(7)<<std::endl;
}

double BindDemo::aMemberFunc(double param)
{
return param * 3;
}

int BindDemo::operator()(int param)
{
return param *5;
}

double aFreeFunc(double param)
{
return param * 2;
}
在useFunction函数中定义了三个function对象,分别托管了自由函数、类静态函数、函数对象。遗憾的是不能托管类成员函数。

四,利用std::bind函数创建闭包
这里再提一个闭包的概念,我觉得通俗的来说,就是闭包将所有需要的内容都放进去了,或者是只留出个别需要调用者填写的内容,当调用时能够统一进行调用。这样说起来一点都不通俗啊。
.h
void useBind();
.cpp
void BindDemo::useBind()
{
//1
using namespace std::placeholders;
std::cout<<std::bind(aFreeFunc,4)()<<std::endl;
std::cout<<std::bind(aFreeFunc,_1)(4)<<std::endl;

//2
std::cout<<std::bind(&BindDemo::aMemberFunc2,*this,4,5,6)()<<std::endl;
std::cout<<std::bind(&BindDemo::aMemberFunc2,this,4,5,6)()<<std::endl;

//3
std::cout<<std::bind(&BindDemo::aMemberFunc,6)()<<std::endl;
// std::cout<<std::bind(&BindDemo::aMemberFunc,this,6)()<<std::endl;

//4
std::cout<<std::bind(*this,6)()<<std::endl;
}
其实也很容易看懂(如果看了第一篇博客的话),第一个参数就是函数指针,注意了自由函数指针和成员函数指针的区别就行了。其中:
1是绑定自由函数,不利用占位符或者是利用占位符的。
2是绑定成员函数,传入的实例对象可以为实例的指针,也可以实例。这里特别要注意一下,如果传入的是实例,那么是重新构造了一个实例对象才穿进去的,如果需要穿个引用进去可以这样:
std::cout<<std::bind(&BindDemo::aMemberFunc2,std::ref(*this),4,5,6)()<<std::endl;
也就是利用std::ref()包装一下,传入引用进去。(其实我写到这里才明白std::ref有什么用,以前还觉得真没用,这才知道,参数的类型是由函数自己定义的,而函数如果本身参数是值类型,那么用户向穿引用进去怎么办?好办,就用std::ref()包装一下即可)。
3是绑定静态函数,注释部分错误
4是绑定函数对象。
另外再注意一下占位符的写法。

五,bind和function的组合
.h
void useBindWithFunction();
.cpp
void BindDemo::useBindWithFunction()
{
//1
using namespace std::placeholders;
std::function<double()> fc1 = std::bind(aFreeFunc,4);
std::cout<<fc1()<<std::endl;
std::function<double(double)> fc2 = std::bind(aFreeFunc,_1);
std::cout<<fc2(2.0)<<std::endl;

//2
std::function<double()> fc3 = std::bind(&BindDemo::aMemberFunc2,*this,4,5,6);
std::cout<<fc3()<<std::endl;
std::function<double(double)> fc4 = std::bind(&BindDemo::aMemberFunc2,*this,_1,5,6);
std::cout<<fc4(2.2)<<std::endl;
std::function<double(double,double)> fc5 = std::bind(&BindDemo::aMemberFunc2,*this,_1,_2,6);
std::cout<<fc5(2.0,3.1)<<std::endl;

//3
std::function<int()> fc6 = std::bind(*this,6);
std::cout<<fc6()<<std::endl;
}
这个也写的比较清楚,前面说过,function接收自由函数指针、成员变量指针、函数对象,而bind的作用就是把各种不同的自由函数指针、成员变量指针、函数对象打包成为一个样式的function,这样就能统一调用——这就是传说中的利用function-bind将设计模式赶出历史舞台的基础。
1是自由函数,2是成员函数,3是函数对象。
需要注意的是,function尖括号里面的容,要和bind形成的内容一致,也就是如在1中,std::function<double()> fc1 = std::bind(aFreeFunc,4);的bind不需要再传入参数,所以尖括号里面类型的参数列表为void,而std::function<double(double)> fc2 = std::bind(aFreeFunc,_1);有一个占位符,那么尖括号里的参数列表为double。
还需要注意的是,bind返回的是一个指针,function这边接收时,不能用引用接收。
这是一个很好的用法,下面给出例子。
六,bind在回调函数中变参数的应用
要求,回调函数的参数个数大于等于function定义的个数。
.h
double aMemberFunc3(int param1,double param2);
void callBackFunc(std::function<double(int,double)> func);
void useCallBackFunc();

类外定义:
inline double aFreeFunc2(int param1,double param2);

.cpp
double BindDemo::aMemberFunc3(int param1, double param2)
{
return param1 +param2;
}
void BindDemo::callBackFunc(std::function<double (int, double)> func)
{
std::cout<<func(5,3.2)<<std::endl;
}
void BindDemo::useCallBackFunc()
{
using namespace std::placeholders;
callBackFunc(aFreeFunc2);
callBackFunc(std::bind(&BindDemo::aMemberFunc3,this,_1,_2));
callBackFunc(std::bind(&BindDemo::aMemberFunc2,this,2.3,_1,_2));
}
double aFreeFunc2(int param1, double param2)
{
return param1 + param2;
}
可以看到,useCallBackFunc中对自由函数回调很简单,就穿进去即可,只要参数对的上,就能运行了。而成员函数的回调就比较麻烦,主要是还要传一个实例对象(或指针)进去,所以必须用bind。而第四句话就是bind我觉得最为重要的用法,将当前所在域的变量传进去,将多于需求(但是也是要满足需求参数的类型的)的内容传个内容进去即可。这其实和lambda用法是一样的,只是lambda在写内容时就知道是否用了环境变量,而这个是在调用时知道是否用了环境变量。

时间: 2024-10-08 20:13:07

2 bind用法详解的相关文章

jQuery的bind()方法用法详解

bind()方法用法详解: 此方法是使用比较频繁的方法之一,虽然在API手册上有着对方法的介绍,但是由于语言简短,例子不够详细,可能会造成不能够完全准确的掌握bind()方法的使用,下面就结合实例介绍一下此方法的使用. 语法格式: $(selector).bind(type,[data],function(eventObject)) 此方法可以为所有匹配元素的特定事件绑定事件处理函数,例如: <!DOCTYPE html> <html> <head> <meta

jQuery 事件用法详解

jQuery 事件用法详解 目录 简介 实现原理 事件操作 绑定事件 解除事件 触发事件 事件委托 事件操作进阶 阻止默认事件 阻止事件传播 阻止事件向后执行 命名空间 自定义事件 事件队列 jquery中文文档 简介 jquery 之所以成为最受欢迎的前端库,很大一部分是得益于它的事件具有良好的语义,优秀的兼容性,并且便于管理和扩展. 在这里我会介绍 jquery 事件的一些比较基础的用法. 实现原理 jquery 事件脱胎于浏览器的 addEventListener (W3) 和 attac

boboJquery表单插件ajaxForm用法详解

插件主要的方法: ajaxFormajaxSubmitformToArrayformSerialize fieldSerializefieldValueclearFormclearFieldsresetForm 示例代码: 1 // wait for the DOM to be loaded 2 $(document).ready(function() {  3    // bind 'myForm' and provide a simple callback function   4    $

live()方法用法详解

live()方法用法详解: 此方法的在jQuery中使用率相当高,并且具有独特的特点,且从其语法结构上不能够看出此方法的独特之处,下面就通过实例详细介绍一下次方法的用法.先看一段代码实例: <!DOCTYPE html> <html> <head> <meta charset=" utf-8"> <meta name="author" content="http://www.softwhy.com/&q

c/c++ 标准库 bind 函数 详解

标准库 bind 函数 详解 bind函数:接收一个函数名作为参数,生成一个新的函数. auto newCallable = bind(callbale, arg_list); arg_list中的参数可能包含入_1, _2等,这些是新函数newCallable的参数. 在这篇博客lambda 表达式 介绍 中,讨论了find_if的第三个参数的问题,当时是用lambda表达式解决的,有了bind函数后,也可以用bind函数解决. 解决办法:bind(check_size, _1, sz) au

银钻娱乐客服15687949443开户关于bind()函数详解

相信很多接触过jQuery的小伙伴对bind()函数一点都不陌生吧,但是很多小伙伴还不是很清bind()的含义与使用,bind()函数用于为每个匹配元素的一个或多个事件绑定事件处理函数.今天我们就带大家详细介绍下jQuery中关于bind()函数详解! 此外,你还可以额外传递给事件处理函数一些所需的数据. 执行bind()时,事件处理函数会绑定到每个匹配元素上.因此你使用bind()所有button元素绑定了click事件,是为当时文档中存在的每个button元素绑定click事件.如果之后你向

Vue1.0用法详解

Vue.js 不支持 IE8 及其以下版本,因为 Vue.js 使用了 IE8 不能实现的 ECMAScript 5 特性. 开发环境部署 可参考使用 vue+webpack. 基本用法 1 2 3 4 5 6 7 8 9 10 11 <div id="app"> {{message}} <input v-model="message"> </div> new Vue({ ele: '#app', data: { message:

js的offsetParent属性用法详解

js的offsetParent属性用法详解:此属性是javascript中较为常用的属性,对于它的良好掌握也是非常有必要的,下面就通过代码实例介绍一下它的用法,希望能够给需要的朋友带来一定的帮助.一.基本介绍:此属性可以返回距离指定元素最近的采用定位(position属性值为fixed.relative或者absolute)父级元素,如果父级元素中没有采用定位的元素,则返回body对象的引用.语法结构: obj.offsetParent 二.代码实例: <!DOCTYPE html> <

python处理word文件:win32com用法详解

目标:用python处理doc文件 方法:引入win32com模块 ************************************************************************** 一.安装 ************************************************************************** 首先要先下载安装win32com模块(起先在linux下装不成功,后在windows下面成功了...) 下载地址:http