本文目录一览:
C++ bind函数
bind是一组用于函数绑定的模板。在对某个函数进行绑定时,可以指定部分参数或全部参数,也可以不指定任何参数,还可以调整各个参数间的顺序。对于未指定的参数,可以使用占位符_1、_2、_3来表示。-1表示绑定后的函数的第1个参数,_2表示绑定后的函数的第2个参数,其他依次类推。
bind可以绑定到普通函数、函数对象、类的成员函数和类的成员变量。下面分别进行介绍。
1、普通函数
1 void nine_arguments(int i1,int i2,int i3,int i4,int i5,int i6,int i7,int i8,int i9);
2 int i1=1, i2=2, i3=3, i4=4, i5=5, i6=6, i7=7, i8=8, i9=9;
3 bind(nine_arguments,_9,_2,_1,_6,_3,_8,_4,_5,_7(i1,i2,i3,i4,i5,i6,i7,i8,i9);
4 bind(nine_arguments,i9,i2,i1,i6,i3,i8,_1,_2,_1)(i8,i9);
5 bind(nine_arguments, i9,i2,i1,i6,i3,i8,i4,i5,i7)();
2、函数对象
1 class CStudent
2 {
3 public:
4 void operator() (string strName, int nAge)
5 {
6 cout strName " : " nAge endl;
7 }
8 };
9 bind(CStudent(), "Mike", _1)(12);
3、类的成员函数
1 struct TAdd
2 {
3 int Add(int x,int y)
4 {
5 return x+y;
6 }
7 };
8 TAdd tAdd;
9 TAdd *p = new TAdd();
10 shared_ptrTAdd *q(p);
11 bind(TAdd::Add, tAdd, 2, 3)();
12 bind(TAdd::Add, p, 2, 3)();
13 bind(TAdd::Add, q, 2, 3)();
4、类的成员变量
1 void Output(const string name)
2 {
3 cout name endl;
4 }
5
6 mapint, string map1;
7 for_each(map1.begin(), map1.end(), bind(Output, bind(mapint,
8 string::value_type::second, _1)));
bind还可以进行嵌套绑定。假设有一个CPerson类,该类有一个获取年龄的接口int GetAge(),现在有一个CPerson对象的vector,需要对其进行排序,则可以如下使用bind:-bind函数
1 vectorCPerson vctPerson;
2 sort(vctPerson.begin(), vctPerson.end(), bind(lessint(),
3 bind(CPerson::GetAge, _1), bind(CPerson::GetAge, _2)));
假设有一个整数的vector, 现在想要获取其中大于20但小于30的整数的个数,则有:
1 count_if(vctNum.begin(), vctNum.end, bind(logic_andbool(),
2 bind(greaterint(), _1, 20), bind(lessint(), _1, 30)));
在使用bind时,还有一些需要特别注意的地方,下面逐一进行介绍。
1、对于指定了值的参数,bind返回的函数对象会保存这些值,并且缺省是以传值方式保存的。考虑下面的代码:
1 void inc(int a) { a++; }
2 int n = 0;
3 bind(inc, n)();
调用bind返回的函数对象后,n仍然等于0。这是由于bind时,传入的是n的拷贝。如果需要传入n的引用,则可以使用ref或cref函数,比如:
1 bind(inc, ref(n))(); // n现在等于1了
2、bind的第一个参数是一个函数对象,不能用占位符来代替。考虑下面的代码:
1 typedef functionvoid (int) Func;
2 vectorFunc vctFunc;
3 for_each(vctFunc.begin(), vctFunc.end(), bind(_1, 5)); // 编译出错
此时,可以借助apply模板。apply模板的第一个参数是传入的函数对象,后面可以有若干个参数,表示函数对象的参数。比如:
1 applyvoid a; // void是函数对象的返回值类型
2 a(f); // 相当于调用f()
3 a(f, x); // 相当于调用f(x)
4 a(f, x, y); // 相当于调用f(x, y)
使用apply后,我们可以将vctFunc中的元素当作占位符传递过来。参考代码如下:
1 for_each(vctFunc.begin(), vctFunc.end(), bind(applyvoid(), _1, 5));
-- 本文来源于创世软件团队博客, 原文地址:
std::bind函数
关于bind的用法:可将bind函数看作是一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表。
其中,newCallable本身是一个可调用对象,arg_list是一个逗号分隔的参数列表,对应给定的callable的参数。
即,当我们调用newCallable时,newCallable会调用callable,并传给它arg_list中的参数。
在我看来 std::bind,其实就是提前绑定某个函数的部分参数或者所有参数后生成一个新的函数。
所以任何函数通过std::bind都可以生成一个无参数函数,这个对统一管理任务,线程池的构造很重要。
jQuery中的bind()函数跟on()函数有什么区别呢?
.bind()与.on()的区别:
(1)是否支持selector这个参数值。由于javascript的事件冒泡特性,如果在父元素上注册了一个事件处理函数,当子元素上发生这个事件的时候,父元素上的事件处理函数也会被触发。
如果使用on的时候,不设置selector,那么on与bind就没有区别了。
(2)on绑定的事件处理函数,对于未来新增的元素一样可以的,和delegate效果相同,而bind则不行。
(3) delegate用法与on()相同,只是参数的顺序不同:
扩展资料:
.bind()与.on()的实际应用:
1.bind()是直接绑定在元素上 ,将一本地地址与一套接口捆绑。如无错误发生,则bind()返回0。否则的话,将返回-1,应用程序可通过WSAGetLastError()获取相应错误代码。
用于事件处理程序
function ClassName(){
this.eventHandler = (function(){
}).bind(this);
}
2.on()则实现事件代理, 可以在匹配元素上绑定一个或者多个事件处理函数。
(1) 用来绑定多事件,并且为同一函数,如:
$('div').on('click mouseover',function(){
//do sth
});
(2)多个事件绑定不同函数,如:
$('div').on({
'click':function(){
//do sth
},
'mouseover':function(){
//do sth
}
});
(3)事件代理,如:
html:
button id="bt1"按钮1/button
jq:
$('#bt1').on('click',function(){
$('body').append('button按钮2/button');
});
$('body').on('click','.bt2',function(){
console.log('这是bt2');
}
参考资料:百度百科-bind()
手动实现bind函数
为什么要自己去实现一个bind函数?
所以,为了理想主义和世界和平(所有浏览器上都能随心所欲调用它),必要的时候需要我们自己去实现一个bind。那么,一个bind函数需要具备什么功能呢?
绑定this、定义初始化参数是它存在的主要意义和价值。MDN对它的定义如下:
鉴于这两个核心作用,我们可以来实现一个简单版看看:
由于arguments是类数组对象,不拥有数组的slice方法,所以需要通过call来将slice的this指向arguments。 args就是调用bind时传入的初始化参数(剔除了第一个参数oThis)。将args与绑定函数执行时的实参arguments通过concat连起来作为参数传入,就实现了bind函数初始化参数的效果。-bind函数
bind函数的另外一个也是最主要的作用:绑定this指向,就是通过将调用bind时的this(self)指向指定的oThis来完成。这样当我们要使用bind绑定某个对象时,执行绑定函数,它的this就永远固定为指定的对象了~-bind函数
到这里,我们已经可以用上面的版本来使用大部分场景了。但是~
但是,这种方案就像前面说的,它会永远地为绑定函数固定this为指定的对象。如果你仔细看过MDN关于bind的描述,你会发现还有一个情况除外:
我们可以通过一个示例来试试看原生的bind对于使用new的情况是如何的:
试验结果发现,obj.name依然是lily而没有变成tom,所以就像MDN描述的那样,如果绑定函数cat是通过new操作符来创建实例对象的话,this会指向创建的新对象tom,而不再固定绑定指定的对象obj。-bind函数
而上面的简易版却没有这样的能力,它能做到的只是永久地绑定指定的this(有兴趣的朋友可以在控制台使用简易版bind试下这个例子看看结果)。这显然不能很好地替代原生的bind函数~
那么,如何才能区分绑定函数有没有通过new操作符来创建一个实例对象,从而进行分类处理呢?
我们知道 检测一个对象是否通过某个构造函数使用new实例化出来的最快的方式是通过 instanceof :
A instanceof B //验证A是否为B的实例
那么,我们就可以这样来实现这个bind:
假设我们将调用bind的函数称为C,将fBound的prototype原型对象指向C的prototype原型对象(上例中就是self),这样的话如果将fBound作为构造函数(使用new操作符)实例化一个对象,那么这个对象也是C的实例,this instanceof self就会返回true。这时就将self指向新创建的对象的this上就可以达到原生bind的效果了(不再固定指定的this)。否则,才使用oThis,即绑定指定的this。-bind函数
但是这样做会有什么影响?将fBound的prototype原型对象直接指向self的prototype原型对象,那么当修改fBound的prototype对象时,self(上述C函数)的prototype对象也会被修改!!考虑到这个问题,我们需要另外一个function来帮我们做个中间人来避免这个问题,我们看看MDN是怎么实现bind的。-bind函数
MDN针对bind没有被广泛支持的兼容性提供了一个实现方案:
发现了吗,和上面经过改造的方案相比,最主要的差异就在于它定义了一个空的function fNOP,通过fNOP来传递原型对象给fBound(通过实例化的方式)。这时,修改fBound的prototype对象,就不会影响到self的prototype对象啦~而且fNOP是空对象,所以几乎不占内存。-bind函数
其实这个思路也是YUI库如何实现继承的方法。他的extend函数如下:
最后一步是将Child的constructor指回Child。
实现一个原生的函数,最重要的是理清楚它的作用和功能,然后逐一去实现它们包括细节,基本上就不会有问题~
这里用到的一些关于 prototype 和 instanceof 的具体含义,可以参考阮一峰老师的 prototype 对象 ,相信对你理解JavaScript的原型链和继承会有帮助~
原文链接: