【cocos2dx】std::function与std::bind 函数指针
来源:互联网 发布:微表情软件白金版 编辑:程序博客网 时间:2024/06/05 11:17
函数指针是指向函数的指针变量。 因而“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。这正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数。如前所述,C在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上是大体一致的。函数指针有两个用途:调用函数和做函数的参数。
函数指针的声明方法为:
返回值类型 ( * 指针变量名) ([形参列表]);
注1:“返回值类型”说明函数的返回类型,“(指针变量名 )”中的括号不能省,括号改变了运算符的优先级。若省略整体则成为一个函数说明,说明了一个返回的数据类型是指针的函数,后面的“形参列表”表示指针变量指向的函数所带的参数列表。例如:
int func(int x); /* 声明一个函数 */
int (*f) (int x); /* 声明一个函数指针 */
f=func; /* 将func函数的首地址赋给指针f */
或者使用下面的方法将函数地址赋给函数指针:
f = &fun;
赋值时函数func不带括号,也不带参数,由于func代表函数的首地址,因此经过赋值以后,指针f就指向函数func(x)的代码的首地址。
注2:函数括号中的形参可有可无,视情况而定。
下面的程序说明了函数指针调用函数的方法:
例一、
#include<stdio.h>int max(int x,int y){ return(x>y?x:y);}int main(){ int(*ptr)(int,int); int a,b,c; ptr=max; scanf("%d%d",&a,&b); c=(*ptr)(a,b); printf("a=%d,b=%d,max=%d",a,b,c; return 0;}
ptr是指向函数的指针变量,所以可把函数max()赋给ptr作为ptr的值,即把max()的入口地址赋给ptr,以后就可以用ptr来调用该函数,实际上ptr和max都指向同一个入口地址,不同就是ptr是一个指针变量,不像函数名称那样是死的,它可以指向任何函数,就看你想怎么做了。在程序中把哪个函数的地址赋给它,它就指向哪个函数。而后用指针变量调用它,因此可以先后指向不同的函数。不过注意,指向函数的指针变量没有++和--运算,用时要小心。
不过,在某些编译器中这是不能通过的。这个例子的补充如下。
应该是这样的:
1.定义函数指针类型:
typedef int (*fun_ptr)(int,int);
2.声明变量,赋值:
fun_ptr max_func=max;
也就是说,赋给函数指针的函数应该和函数指针所指的函数原型是一致的。
例二、
#include<stdio.h>void FileFunc(){ printf("FileFunc\n");}void EditFunc(){ printf("EditFunc\n");}void main(){ typedef void(*funcp)(); funcppfun=FileFunc; pfun(); pfun=EditFunc; pfun();}
上面是介绍函数指针。
下面介绍 std::function与std::bind 函数指针
function模板类和bind模板函数,使用它们可以实现类似函数指针的功能,但却却比函数指针更加灵活,特别是函数指向类 的非静态成员函数时。
std::function可以绑定到全局函数/类静态成员函数(类静态成员函数与全局函数没有区别),如果要绑定到类的非静态成员函数,则需要使用std::bind。
#include <iostream>#include <functional>using namespace std;typedef std::function<void ()> fp;void g_fun(){cout<<"g_fun()"<<endl;}class A{public:static void A_fun_static(){cout<<"A_fun_static()"<<endl;}void A_fun(){cout<<"A_fun()"<<endl;}void A_fun_int(int i){cout<<"A_fun_int() "<<i<<endl;}//非静态类成员,因为含有this指针,所以需要使用bindvoid init(){fp fp1=std::bind(&A::A_fun,this);fp1();}void init2(){typedef std::function<void (int)> fpi;//对于参数要使用占位符 std::placeholders::_1fpi f=std::bind(&A::A_fun_int,this,std::placeholders::_1);f(5);}};int main(){//绑定到全局函数fp f2=fp(&g_fun);f2();//绑定到类静态成员函数fp f1=fp(&A::A_fun_static);f1();A().init();A().init2();return 0;}
同时,std::bind绑定到虚函数时会表现出多态行为。
#include <iostream>#include <functional>using namespace std;typedef std::function<void ()> fp;class A{public:virtual void f(){cout<<"A::f()"<<endl;}void init(){//std::bind可以表现出多态行为fp f=std::bind(&A::f,this);f();}};class B:public A{public:virtual void f(){cout<<"B::f()"<<endl;}};int main(){A* pa=new B;pa->init();return 0;}
转自:http://blog.csdn.net/qq575787460/article/details/8531397
//==========================================================
在写MenuItemImage中遇到了问题,就是后面的回调函数怎么写,于是找到了源码,结果是这样的。。。
// Image Item auto item2 = MenuItemImage::create(s_SendScore, s_PressSendScore, CC_CALLBACK_1(MenuLayerMainMenu::menuCallback2, this) );
这里看到CC_CALLBACK_1又不懂了,继续F12.。。。
// new callbacks based on C++11#define CC_CALLBACK_0(__selector__,__target__, ...) std::bind(&__selector__,__target__, ##__VA_ARGS__)#define CC_CALLBACK_1(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, ##__VA_ARGS__)#define CC_CALLBACK_2(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, ##__VA_ARGS__)#define CC_CALLBACK_3(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, ##__VA_ARGS__)
就找到了这样的东西,然后继续搜索。。。
告诉我去了解下std::function与std::bind 函数指针
又找到了如下的内容:
//========================================================
下文地址:http://blog.csdn.net/star530/article/details/21245565
本篇的主题就是揭露CC_CALLBACK 与 std::bind之间不可告人的秘密......
首先看一段代码:
//先是创建3个精灵boy = Sprite::create("boy.png");//创建boyboy->setPosition(Point(visibleSize.width/2,visibleSize.height/2));this->addChild(boy,1);girl_1 = Sprite::create("girl_1.png");//创建girl1girl_1->setPosition(Point(visibleSize.width/3,visibleSize.height/2));girl_1->setTag(10);this->addChild(girl_1,1);girl_2 = Sprite::create("girl_3.png");//创建girl2girl_2->setPosition(Point(2*visibleSize.width/3,visibleSize.height/2));girl_2->setTag(20);this->addChild(girl_2,1);//让boy运动,通过Callfunc回调到callback1boy->runAction(CCSequence::create(MoveBy::create(1.0f,Point(0,100)),CallFunc::create(CC_CALLBACK_0(HelloWorld::callback1,this)),NULL));
三个回调函数的实现:
void HelloWorld::callback1(){CCLOG("in callback1");//girl1运动,最后回调到callback2girl_1->runAction(CCSequence::create(MoveBy::create(1.0f,Point(0,150)),CallFunc::create(CC_CALLBACK_0(HelloWorld::callback2,this,girl_1)),NULL));}void HelloWorld::callback2(Node* sender){//girl2运动,最后回调到callback3girl_2->runAction(CCSequence::create(MoveBy::create(1.0f,Point(0,200)),CallFunc::create(CC_CALLBACK_0(HelloWorld::callback3,this,girl_2,99)),NULL));CCLOG("in callback2,sender tag is:%d",(Sprite*)sender->getTag());}void HelloWorld::callback3(Node* sender, long data){//最终输出CCLOG("in callback3,everything is OK,sender tag is:%d,date is:%ld",(Sprite*)sender->getTag(),data);CCLOG("girl2 dandan ask:what fake the CC_CALLBACK is?");}
整个过程就是boy“勾引”girl1,但girl1显然对异性兴趣不大,于是她也勾引girl2......可是,girl2对同性异性都没兴趣,她只是淡淡的说了句:CC_CALLBACK到底是什么?,调试如图:
好吧,先让我回口血,然后再来回答girl2的问题:CC_CALLBACK到底是什么碗糕(东东)?
我们先进CC_CALLBACK源码里看看:
// new callbacks based on C++11#define CC_CALLBACK_0(__selector__,__target__, ...) std::bind(&__selector__,__target__, ##__VA_ARGS__)#define CC_CALLBACK_1(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, ##__VA_ARGS__)#define CC_CALLBACK_2(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, ##__VA_ARGS__)#define CC_CALLBACK_3(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3 ##__VA_ARGS__)看完后恍然大悟!不看不知道,一看...和没看一样...
这里主要注意两点:一是 std::bind,二是##_VA_ARGS_; ##_VA_ARGS_是可变参数宏,我就不多说了。重点讲的是std::bind。
std::bind是在C++ 11里新加入的成员。可以将bind函数看作一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表.
调用bind的一般形式为:
auto newCallback = bind(callback,arg_list);
其中,newCallback是一个可调用对象,arg_list是可以用逗号分隔的参数列表,至于是啥参数,那就看callback函数里有啥参数啦。也就是说,当我们调用newCallback时,newCallback会调用函数callback,并传递参数arg_list给callback.
看完上面的内容你的理解可能还比较模糊,那直接来个例子:有一个函数callback,如下,
int callback(int one,char two,double three);
下面我们用bind来调用callback
auto newCallback = bind(callback,_1,_2,1.5);int x = newCallback(10,'h'); //这句相当于:int x = callback(10,'h',1.5);
“_1″是一个占位符对象,用于表示当函数callback通过函数newCallback进行调用时,函数newCallback的第一个参数在函数callback的参数列表中的位置。第一个参数称为”_1″, 第二个参数为”_2″,依此类推,有意思吧。至于‘1.5’是指默认参数,它处于_1和_2的后面,所以它就是double类型的参数了.
在强调一点就是:_1这类占位符都定义在一个名为placeholders的命名空间中,而这个命名空间本身定义在std的命名空间中。为了使用这些名字,两个命名空间都要写上,如:
std::placeholders::_1;
这样编写贼麻烦,所以在要使用_1时,可以加上这么一句:
using namespace namespace_name; 恩,ok
恩,bind就介绍到这,讲的比较浅,不理解的可以百度研究下。最后再回过头来看下CC_CALLBACK的定义,是不是清晰多了?
最后在举个例子吧,还是之前的boy,girl1,girl2,只是他们之间传递“爱意”的方式要换下了。不用CC_CALLBACK,改用std::bind。代码如下 :
//让boy运动,通过Callfunc回调到callback1boy->runAction(CCSequence::create(MoveBy::create(1.0f,Point(0,100)),CallFunc::create(std::bind(&HelloWorld::callback1,this)),NULL));
void HelloWorld::callback1(){CCLOG("in callback1");//girl1运动,最后回调到callback2girl_1->runAction(CCSequence::create(MoveBy::create(1.0f,Point(0,150)),CallFunc::create(std::bind(&HelloWorld::callback2,this,girl_1)),NULL));CCLOG("boy ask girl_1:can you do my girlFriends?");}void HelloWorld::callback2(Node* sender){//girl2运动,最后回调到callback3girl_2->runAction(CCSequence::create(MoveBy::create(1.0f,Point(0,200)),CallFunc::create(std::bind(&HelloWorld::callback3,this,girl_1,99)),NULL));CCLOG("in callback2,sender tag is:%d",(Sprite*)sender->getTag());CCLOG("girl_1 ask girl_2:I love girl_2");}void HelloWorld::callback3(Node* sender, long data){//最终输出CCLOG("in callback3,everything is OK,sender tag is:%d,date is:%ld",(Sprite*)sender->getTag(),data);CCLOG("girl2 dandan say:I know how to use CC_CALLBACK!");}
恩,就是这样子了。bind与CC_CALLBACK之间的关系就是这么的...简单。
尊重原创,转载请注定来自star特530: http://blog.csdn.net/start530/article/details/21245565
- 【cocos2dx】std::function与std::bind 函数指针
- std::function与std::bind 函数指针
- std::function与std::bind 函数指针
- std::function与std::bind 函数指针
- std::function与std::bind 函数指针
- std::function与std::bind 函数指针
- std::function与std::bind 函数指针
- std::function与std::bind 函数指针
- std::function与std::bind 函数指针
- std::function与std::bind 函数指针
- std::function与std::bind 函数指针
- std::function与std::bind 函数指针
- std::function与std::bind 函数指针
- std::function与std::bind 函数指针
- std::function与std::bind 函数指针
- std::function与std::bind 函数指针
- std::function与std::bind 函数指针
- std::function与std::bind 函数指针
- UVA - 10790 How Many Points of Intersection?
- CUDA初学,实现1000*256的数组运算
- WPF——画刷
- linux 下 查看 磁盘空间
- Poj 2312 BFS+优先队列
- 【cocos2dx】std::function与std::bind 函数指针
- Java使用jxl对excel文件进行简单的读写
- 利用pymongo操作mongoDB数据库
- 14.约瑟夫环
- git笔记
- arm-linux工具的功能
- 禁止键入非法值
- [Leetcode]Remove Duplicates from Sorted List II
- ORCAD 快速加页码