bind函数的用法和参数问题

匿名用户不能发表回复!|
每天回帖即可获得10分可用分!小技巧:
你还可以输入10000个字符
(Ctrl+Enter)
请遵守CSDN,不得违反国家法律法规。
转载文章请注明出自“CSDN(www.csdn.net)”。如是商业用途请联系原作者。18936人阅读
s2: 实战Network编程(135)
&&&&& 前面我们已经说了, 套接字也创建了, “地方”也定义了,下面就需要将socket放置在这个“地方”(TCP),将他们紧紧地捆绑在一起,用bind函数吧, 我们来看看函数原型:
int PASCAL FAR bind (SOCKET s, const struct sockaddr FAR *addr, int namelen);
&&&&&第一个参数当然是待绑定的套接字啦,第二个参数是标识绑定在哪个“地方”, 第三个参数是这个“地方”的占地大小。
&&&& 返回值表示绑定操作是否成功,0表示成功, -1表示不成功。函数的返回值千万不要忽视,上次就被人说了。
&&& 一般是这么调用的:
&& & iRet = bind(sockSrv,(SOCKADDR*)&addrSrv, sizeof(SOCKADDR)); // 注意强制转换
& & &我们来对比一下文件I/O操作和网络I/O操作: 打开一个文件后, 便可以对文件进行读写操作了, 但是, 网络I/O实际上有三个步骤来完成这个功能:
& & &1. 打开/创建socket
& & &2. 命名socket, 我们知道, socket名称包含&协议, ip地址, &端口号&这三个要素, 而命名就是通过调用bind函数把socket与这三个要素绑定一起来。
& & &3. 建立连接
& & &在后面的博文中, 我们将继续学习bind.
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:3818209次
积分:52106
积分:52106
排名:第60名
原创:1823篇
转载:162篇
评论:1994条
(27)(83)(20)(74)(61)(14)(32)(52)(8)(10)(28)(56)(32)(26)(15)(42)(63)(38)(39)(75)(43)(4)(20)(33)(17)(11)(7)(48)(53)(51)(52)(35)(20)(53)(41)(35)(13)(32)(36)(7)(1)(47)(23)(26)(4)(13)(4)(19)(72)(13)(2)(14)(45)(32)(7)(3)(28)(53)(106)(68)
(window.slotbydup = window.slotbydup || []).push({
id: '4740887',
container: s,
size: '250,250',
display: 'inlay-fix'C++ VC(23)
函数绑定bind函数用于把某种形式的参数列表与已知的函数进行绑定,形成新的函数。这种更改已有函数调用模式的做法,就叫函数绑定。需要指出:bind就是函数适配器。
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
using namespace std::
int main()
auto fun = [](int *array, int n, int num){
for (int i = 0; i & i++)
if (array[i] & num)
cout && array[i] &&
int array[] = { 1, 3, 5, 7, 9 };
//_1,_2 是占位符
auto fun1 = bind(fun, _1, _2, 5);
//等价于调用fun(array, sizeof(array) / sizeof(*array), 5);
fun1(array, sizeof(array) / sizeof(*array));
cin.get();
实例很简单,大家一看就明白。但有必要说明一下:
问题:什么是适配器?
适配器是一种机制,把已有的东西改吧改吧、限制限制,从而让它适应新的逻辑。需要指出,容器、迭代器和函数都有适配器。
bind就是一个函数适配器,它接受一个可调用对象,生成一个新的可调用对象来适应原对象的参数列表。
bind使用的一般形式:
auto newfun = bind(fun, arg_list);
其中fun是一函数,arg_list是用逗号隔开的参数列表。调用newfun(),newfun会调用fun(arg_list);
bind的常见用法一
在本例中,fun()的调用需要传递三个参数,而用bind()进行绑定后只需两个参数了,因为第三个参数在绑定时被固定了下来。减少函数参数的调用,这是bind最常见的用法。
2._1,_2是占位符,定义于命名空间placeholders中。_1是newfun的第一个参数,_2是newfun的第二个参数,以此类推。
bind的常见用法二
bind的另一个常见的用法是更改参数的调用顺序。如
int fun(int a, int b);
auto newfun = bind(fun, _2, _1);
调用newfun(1, 2);相当于调用fun(2, 1);
顺便说下什么是占位参数?
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
int fun(int a, int b, int)
return a +
调用方式类似于 fun(1, 2, 0);
这个fun函数的设计很有意思,它接受三个int型的参数,但第三个参数没有给出变量名,以至于function body中无法使用该参数,既然已经设计出来了,却不用?这是啥意思?
这个就是占位参数,它为函数的升级提供了预留的接口。
绑定类成员函数
[cpp] view plain copy
using namespace std::
class MyClass
void fun1(void)
cout && “void fun1(void)” &&
int fun2(int i)
cout && “int fun2(int i)” && ” i = ” && i &&
int main()
cout && “*使用bind绑定类成员函数*by David” &&
//使用类对象绑定
auto fun1 = bind(&MyClass::fun1, my);
MyClass *p;
//使用类指针绑定
auto fun2 = bind(&MyClass::fun2, p, _1);
int i = fun2(1);
cout && “i = ” && i &&
cin.get();
对类成员函数进行绑定与对普通函数进行绑定,稍有不同:对类成员函数绑定需要用到类对象或类指针。这个很好理解:类成员函数被封装在类中,故不可随便访问,需借助类对象或类指针。
下面一段代码展示了类成员变量和类成员函数的类型
[cpp] view plain copy
class MyClass
void fun(int i)
int main(void)
cout && typeid(&MyClass::var).name() &&
cout && typeid(&MyClass::fun).name() &&
cin.get();
从运行结果看,普通成员和类类型成员是不同的。
函数绑定bind可以对普通函数或类成员函数进行绑定。它的作用有两点:一是减少调用参数;二是更改参数调用顺序。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:16790次
排名:千里之外
转载:23篇
(2)(11)(1)(5)(2)(1)(4)(1)(2)
(window.slotbydup = window.slotbydup || []).push({
id: '4740881',
container: s,
size: '200,200',
display: 'inlay-fix'为什么需要bind
var name = "The Window";
var object = {
name: "My Object",
getNameFunc: function () {
return function () {
return this.
alert(object.getNameFunc()()); //"The Window"
object.getNameFunc()返回一个匿名函数,在全局环境调用该函数,this指向的全局对象
解决这一问题,可以像下面这样,将匿名函数外部作用域中this对象保存在闭包能够访问到的变量中
var name = "The Window";
var object = {
name: "My Object",
getNameFunc: function () {
var that = this;
return function () {
return that.
alert(object.getNameFunc()()); //"My Object"
上述解决方法需要修改对象的方法,如果不能修改原对象的方法,该如何做呢?
这时,我们可以像下面这样,使用apply或call方法指定函数的作用域
var name = "The Window";
var object = {
name: "My Object",
getNameFunc: function () {
return function () {
return this.
var func=object.getNameFunc();
alert(func.apply(object)); //"My Object"
通过apply、call,已经可以输出预期的My Object
但是,每次调用时都需要以func.apply(object)的形式调用,这不是很怪么
理想的调用方式,当然是在通过某种处理后,之后可以以func()形式调用,像下面这样
var name = "The Window";
var object = {
name: "My Object",
getNameFunc: function () {
return function () {
return this.
var func=object.getNameFunc();
func=func.bind(object);
alert(func()); //"My Object"
ECMAScript 5中的bind
&ECMAScript 5定了了bind方法,这个方法会创建一个函数实例,其this值会被绑定到传给bind函数的值,上面代码给出了bind函数的使用方式,再给一个简单示例。
window.color="red";
var o={color:"blue"};
function sayColor(){
alert(this.color);
var func=sayColor.bind(o);
func();//"blue"
虽然大部分浏览器中已经可以使用ECMAScript 5定义的这个方法,但在少数不支持的浏览器中你还是会遇到兼容性问题,这是如何处理呢?
通过上面apply、call方法使用示例 ,可以像下面这样提供一个解决方案
Function.prototype.bind=Function.prototype.bind||
function(context){
var self=this;
return function()
return self.apply(context,arguments);
Prototype.js中的bind
// The .bind method from Prototype.js
Function.prototype.bind = function(){
var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift();
return function(){
return fn.apply(object,
args.concat(Array.prototype.slice.call(arguments)));
&上述代码中,
args=Array.prototype.slice.call(arguments)将调用bind函数时参数集合arguments转换为数组array
object=args.shift()将args数组第一个元素取出作为当前对象
匿名函数中,调用args.concat(Array.prototype.slice.call(arguments))是为了将调用匿名函数时传入的参数与调用bind时参数合并成一个参数数组
以一个调用示例来看上述过程
var obj = { x: 'prop x' };
//args = Array.prototype.slice.call(arguments)后args = [obj, 12, 23 ]//object=args.shift()后,args =[12, 23] ,object =objvar boundExample = example.bind(obj, 12, 23);
boundExample(36, 49); // arguments =& 36, 49 ,调用args.concat(Array.prototype.slice.call(arguments))后,arguments that our example() function receives =& [12, 23, 36, 49]
Firefox中的bind
if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
if (typeof this !== "function") {
// closest thing possible to the ECMAScript 5 internal IsCallable function
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function () {},
fBound = function () {
return fToBind.apply(this instanceof fNOP && oThis
: oThis || window,
aArgs.concat(Array.prototype.slice.call(arguments)));
fNOP.prototype = this.
fBound.prototype = new fNOP();
Firefox为bind提供了一个兼容实现,主要代码与prototype.js中实现类似,不再逐句解释了
阅读(...) 评论()下次自动登录
现在的位置:
& 综合 & 正文
boost::bind
当我们使用函数时习惯于C函数的格式,即如下形式resulttype funname( arglist );返回值类型 函数名( 参数列表 );在Boost.Function中,我们可以方便的定义定义函数对象。不过在定义用来表示类成员函数的函数对象时第一个参数是类指针。而且在调用时,要传入一个类实例的指针。这样用起来并不是很方便,因为调用者要知道类实例。这实际上没有实现解耦。而解耦是我们使用回调或委托设计的一个目标。为了解决这个问题,我们要使用Boost.Bind库Boost.Bind是一个函数对象工厂。他用来产生我们需要的函数对象。好了,有了它,你可以在你设计中大量使用Boost.Function。不用再去定义类成员函数形式的函数对象啦,只用定义普通函数对象。一个简单的例子class CExample{public:
bool printstr( const std::string &str )
std::cout && "CExample::printstr" && str && std::
}};//定义一个函数对象boost::function& bool ( const std::string& ) &//用Boost.Bind创建一个函数对象,赋给printstrCEprintstr = boost::bind( &CExample::printstr, &example, _1 );好了,我们创建了一个函数对象,而且调用时不再需要类实例拉。用Boost.Function和Boost.Bind大大的简化了Command模式的实现。在上面的例子中要个古怪的对象"_1"。这个叫做站位符,他代表这个位置有个参数,但现在还不知道参数是什么。_1代表参数列表中的第一个位置上的参数。Boost.Bind一共定义了9个站位符对象。如下_1,_2,_3,_4,_5,_6,_7,_8,_9。分别代表参数列表中位子。Boost.Bind产生的函数对象可以直接使用,利用上面的例子。bool b = boost::bind( &CExample::printstr, &example, _1 )( "Hello World" );
Boost::bind
一 Boost::bind
在STL中,我们经常需要使用bind1st,bind2st函数绑定器和fun_ptr,mem_fun等函数适配器,这些函数绑定器和函数适配器使用起来比较麻
烦,需要根据是全局函数还是类的成员函数,是一个参数还是多个参数等做出不同的选择,而且有些情况使用STL提供的不能满足要求,所以如
果可以我们最好使用boost提供的bind,它提供了统一的接口,提供了更多的支持,比如说它增加了shared_ptr,虚函数,类成员的绑定。
二 源码剖析
1) bind1st,bind2st函数绑定器,把二元函数对象变为一元函数对象。
2) mem_fun,把成员函数变为函数对象。
3) fun_ptr,把一般的全局函数变为函数对象。
4) boost::bind(),包含了以上所有的功能。
1)区别与mem_fun和fun_ptr
#include &functional&#include &iostream&#include &string&#include "boost/bind.hpp"class some_class{public:void print_string(const std::string& s)const{ std::cout && s && '\n'; }void print_classname(){ std::cout && "some_class" && std:: }};void print_string(const std::string s){
std::cout && s && '\n';}void print_functionname(){ std::cout && "Print_functionname" &&std::}int main(){ std::ptr_fun(&print_string)("hello1");//std::ptr_fun&void&(&print_functionname); some_class sc0; std::mem_fun_ref(&some_class::print_classname)(sc0); std::mem_fun_ref&void,some_class&(&some_class::print_classname)(sc0);//std::mem_fun1_ref&void,some_class,const std::stirng&(&some_class::print_string)(sc0,"hello2"); (boost::bind(&print_string,_1))("Hello func!"); boost::bind(&print_functionname); some_ (boost::bind(&some_class::print_classname,_1)(sc)); (boost::bind(&some_class::print_string,_1,_2))(sc,"Hello member!");}
2)区别与bind1st和bind2st
#include &functional&#include &iostream&#include &string&#include &vector&#include &algorithm&#include "boost/bind.hpp"void main(){ std::vector&int& ints.push_back(7); ints.push_back(4); ints.push_back(12); ints.push_back(10);int count=std::count_if(ints.begin(), ints.end(), boost::bind(std::logical_and&bool&(),boost::bind(std::greater&int&(),_1,5),boost::bind(std::less_equal&int&(),_1,10)) ); std::cout && count && '\n'; std::vector&int&::iterator int_it=std::find_if(ints.begin(), ints.end(), boost::bind(std::logical_and&bool&(),boost::bind(std::greater&int&(),_1,5),boost::bind(std::less_equal&int&(),_1,10)) );if (int_it!=ints.end()){
std::cout && *int_it && '\n';}}
3)区别传ref和传instance
// bind instance or reference#include &functional&#include &iostream&#include &string&#include &vector&#include &algorithm&#include "boost/bind.hpp"class tracer{public:
{ std::cout && "tracer::tracer()\n"; }
tracer(const tracer& other)
{ std::cout && "tracer::tracer(const tracer& other)\n"; } tracer&operator=(const tracer& other){
std::cout && "tracer& tracer::operator=(const tracer& other)\n";return *this; }
{ std::cout && "tracer::~tracer()\n"; }void print(const std::string& s)const{
std::cout && s && '\n'; }};void main(){ boost::bind(&tracer::print,t,_1)(std::string("I'm called on a copy of t\n")); tracer t1; boost::bind(&tracer::print,boost::ref(t1),_1)( std::string("I'm called directly on t\n"));}
4)绑定虚函数
//bind vitual class function#include &functional&#include &iostream&#include &string&#include &vector&#include &algorithm&#include "boost/bind.hpp"classbase{public:virtualvoid print()const{
std::cout && "I am base.\n"; }virtual
~base(){}};class derived :publicbase{public:void print()const{
std::cout && "I am derived.\n"; }};void main(){base boost::bind(&base::print,_1)(b); boost::bind(&base::print,_1)(d);}
5)绑定成员变量
// bind class's member#include &functional&#include &iostream&#include &string&#include &vector&#include &algorithm&#include "boost/bind.hpp"class personal_info{ std::string name_; std::string surname_; unsignedint age_;public:
personal_info(const std::string& n,const std::string& s,unsignedint age):name_(n),surname_(s),age_(age){}
std::string name()
{return name_;}
std::string surname()
{return surname_;}
unsigned int age()
{return age_;}};void main(){ std::vector&personal_info& vec.push_back(personal_info("Little","John",30)); vec.push_back(personal_info("Friar", "Tuck",50)); vec.push_back(personal_info("Robin", "Hood",40)); std::sort(vec.begin(), vec.end(), boost::bind(std::less&unsignedint&(),boost::bind(&personal_info::age,_1),boost::bind(&personal_info::age,_2)) ); std::sort(vec.begin(), vec.end(), boost::bind(std::less&std::string&(),boost::bind(&personal_info::surname,_1),boost::bind(&personal_info::surname,_2)) );}
1) 现在的类库最多可以支持9个参数。
2)在绑定一个成员函数时,bind 表达式的第一个参数必须是成员函数所在类的实例!理解这个规则的最容易的方法是,这个显式的参数将取
替隐式的 this ,被传递给所有的非静态成员函数。细心的读者将会留意到,实际上这意味着对于成员函数的绑定器来说,只能支持八个参数
,因为第一个要用于传递实际的对象。
3)当我们传递某种类型的实例给一个 bind 表达式时,它将被复制,除非我们显式地告诉 bind 不要复制它。要避免复制,我们必须告诉
bind 我们想传递引用而不是它所假定的传值。我们要用 boost::ref 和 boost::cref (分别用于引用和 const 引用)来做到这一点,它们也是
Boost.Bind 库的一部分。还有一种避免复制的方法;就是通过指针来传递参数而不是通过值来传递。
4) 通过 Boost.Bind, 你可以象使用非虚拟函数一样使用虚拟函数,即把它绑定到最先声明该成员函数为虚拟的基类的那个虚拟函数上。这
个绑定器就可以用于所有的派生类。如果你绑定到其它派生类,你就限制了可以使用这个绑定器的类。
5)bind还可以绑定成员变量。
bind并不是一个单独的类或函数,而是非常庞大的家族,依据绑定的参数个数和要绑定的调用对象类型,总共有十个不同的形式,但它们的名字都叫bind. bind接受的第一个参数必须是一个可调用对象f,包括函数,函数指针,函数对象和成员函数,之后bind接受最多9个参数,参数的数量必须与f的参数数量相等 _1,_2这些一直可以到9,是占位符,必须在绑定表达式中提供函数要求的所有参数,无论是真实参数还是占位符均可以。占位符不可以超过函数参数数量。 绑定普通函数:
#include&boost/bind.hpp&
#include&iostream&
void fun(int a,int b){
cout && a+b &&
int main()
bind(fun,1,2)();//fun(1,2)
bind(fun,_1,_2)(1,2);//fun(1,2)
bind(fun,_2,_1)(1,2);//fun(2,1)
bind(fun,_2,_2)(1,2);//fun(2,2)
bind(fun,_1,3)(1);//fun(1,3)
绑定成员函数
#include&boost/bind.hpp&
#include&iostream&
#include&vector&
#include&algorithm&
struct point
point(int a=0,int b=0):x(a),y(b){}
void print(){
cout && "(" && x && "," && y && ")\n";
void setX(int a){
cout && "setX:" && a &&
void setXY(int x,int y){
cout && "setX:" && x && ",setY:" && y &&
void setXYZ(int x,int y,int z){
cout && "setX:" && x && ",setY:" && y && "setZ:" && z &&
int main()
point p1,p2;
bind(&point::setX,p1,_1)(10);
bind(&point::setXY,p1,_1,_2)(10,20);
bind(&point::setXYZ,p2,_1,_2,_3)(10,20,30);
vector&point& v(10);
//for_each的时候只需要_1就可以了
for_each(v.begin(),v.end(),bind(&point::print,_1));
for_each(v.begin(),v.end(),bind(&point::setX,_1,10));
for_each(v.begin(),v.end(),bind(&point::setXY,_1,10,20));
for_each(v.begin(),v.end(),bind(&point::setXYZ,_1,10,20,30));
setX:10,setY:20
setX:10,setY:20setZ:30
setX:10,setY:20
setX:10,setY:20
setX:10,setY:20
setX:10,setY:20
setX:10,setY:20
setX:10,setY:20
setX:10,setY:20
setX:10,setY:20
setX:10,setY:20
setX:10,setY:20
setX:10,setY:20setZ:30
setX:10,setY:20setZ:30
setX:10,setY:20setZ:30
setX:10,setY:20setZ:30
setX:10,setY:20setZ:30
setX:10,setY:20setZ:30
setX:10,setY:20setZ:30
setX:10,setY:20setZ:30
setX:10,setY:20setZ:30
setX:10,setY:20setZ:30
&&&&推荐文章:
【上篇】【下篇】}

我要回帖

更多关于 bind函数的用法和参数 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信