函数指针是指向函数的指针变量。 因而“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。这正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数。如前所述,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,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指针,所以需要使用bind
	void init()
	{
		fp fp1=std::bind(&A::A_fun,this);
		fp1();
	}

	void init2()
	{
		typedef std::function<void (int)> fpi;
		//对于参数要使用占位符 std::placeholders::_1
		fpi 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__,##__VA_ARGS__)
#define CC_CALLBACK_1(__selector__,std::placeholders::_1,##__VA_ARGS__)
#define CC_CALLBACK_2(__selector__,std::placeholders::_2,##__VA_ARGS__)
#define CC_CALLBACK_3(__selector__,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");//创建boy
boy->setPosition(Point(visibleSize.width/2,visibleSize.height/2));
this->addChild(boy,1);

girl_1 = Sprite::create("girl_1.png");//创建girl1
girl_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");//创建girl2
girl_2->setPosition(Point(2*visibleSize.width/3,visibleSize.height/2));
girl_2->setTag(20);
this->addChild(girl_2,1);

//让boy运动,通过Callfunc回调到callback1
boy->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运动,最后回调到callback2
	girl_1->runAction(CCSequence::create(MoveBy::create(1.0f,150)),CallFunc::create(CC_CALLBACK_0(HelloWorld::callback2,girl_1)),NULL));
}
void HelloWorld::callback2(Node* sender)
{
	//girl2运动,最后回调到callback3
	girl_2->runAction(CCSequence::create(MoveBy::create(1.0f,200)),CallFunc::create(CC_CALLBACK_0(HelloWorld::callback3,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__,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回调到callback1
boy->runAction(CCSequence::create(MoveBy::create(1.0f,CallFunc::create(std::bind(&HelloWorld::callback1,NULL));

void HelloWorld::callback1()
{
	cclOG("in callback1");
	//girl1运动,最后回调到callback2
	girl_1->runAction(CCSequence::create(MoveBy::create(1.0f,CallFunc::create(std::bind(&HelloWorld::callback2,NULL));
	cclOG("boy ask girl_1:can you do my girlFriends?");
}
void HelloWorld::callback2(Node* sender)
{
	//girl2运动,最后回调到callback3
	girl_2->runAction(CCSequence::create(MoveBy::create(1.0f,CallFunc::create(std::bind(&HelloWorld::callback3,girl_1,(Sprite*)sender->getTag());
	cclOG("girl_1 ask girl_2:I love girl_2");
}
void HelloWorld::callback3(Node* sender,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 函数指针的更多相关文章

  1. ios – 如何使用双指针声明NSString的变量

    我想使用双指针,我试图像这样声明.但是,Xcode向我展示了错误“指向非const类型’Nsstring*’的指针,没有明确的所有权”并且无法编译.最后我想这样做.请告诉我任何建议.解决方法更改为此以便您可以明确指定所有权:输出:在__strong上Hereisthedocumentation.

  2. swift与Objective-C的互用性

    在Objective-C中,你用一个空的选项设置标示恒为零。由于简单的用于定义常量的宏会被直接被映射成Swift全局量,Swift编译器会自动引进在C或Objective-C源文件中定义的简单宏。您在C和Objective-C使用复杂的宏以避免类型检查的限制,或避免重新键入大量的样板代码。因此,在C和Objective-C源文件中定义的复杂宏在Swift是不能使用的。编译配置Swift代码和C、Objective-C代码被有条件地,以不同方式编辑。

  3. swift -函数、函数指针

  4. 《从零开始学Swift》学习笔记Day 71——Swift与C/C++混合编程之数据类型映射

    而在Swift语言中是不能直接使用C数据类型,苹果公司为Swift语言提供与C语言相对应数据类型。代码中CUnsignedChar是将Int类型转化为C语言unsignedchar类型,在Swift中使用CUnsignedChar表示。从表可见针对C语言多样的指针形式,Swift主要通过提供了三种不安全的泛型指针类型:UnsafePointer、UnsafeMutablePointer和AutoreleasingUnsafeMutablePointer。T是泛型占位符,表示不同的数据类型。另外,还有cop

  5. swift学习笔记-----swift中的指针

    swift语言为了简化,把指针隐形化了。事实上,swift是支持使用指针的。苹果已经公开了swift的源码,这个大家都可以去看。虽然如此,还是可以使用的,那么这就是使得字节流解析,在swift中变成了可能。但你的项目迁移到swift以后,这些函数你就要在C中实现,然后用swift去调用,这样做当然没有错。

  6. 《从零开始学Swift》学习笔记Day 71――Swift与C/C++混合编程之数据类型映射

    而在Swift语言中是不能直接使用C数据类型,苹果公司为Swift语言提供与C语言相对应数据类型。代码中CUnsignedChar是将Int类型转化为C语言unsignedchar类型,在Swift中使用CUnsignedChar表示。从表可见针对C语言多样的指针形式,Swift主要通过提供了三种不安全的泛型指针类型:UnsafePointer、UnsafeMutablePointer和AutoreleasingUnsafeMutablePointer。T是泛型占位符,表示不同的数据类型。另外,还有cop

  7. 【Swift】Swift黑魔法 - Runtime

    这样就需要用到MethodSwizzling了MethodSwizzling,其作用就是在不修改任何代码的前提下,交换两个方法的声明与实现为了实现上述需求,我们首先需要使用extension,对SwizzlingDemo进行扩展:我们在SwizzlingDemo中扩展了一个方法:swizzlePrintMethod()从代码中可以很清晰地看出:我们首先获取了printA和printB两个方法的Selector再根据两个Selector取出了两个方法的Method最后交换了两个方法的Method,Swizz

  8. Swift中如何转换不同类型的Mutable指针

    在Swift中我们拥有强大高级逻辑抽象能力的同时,低级底层操作被刻意的限制了.但是有些情况下我们仍然想做一些在C语言中的hack工作,下面本猫就带大家看一看如何做这样的事.hackingishappy!!!如上代码我们只要在闭包中返回一个Char指针就可以了,怎么做呢?这就需要借助另一个超级强大的方法unsafeBitCast,该方法将一种类型的变量内容强制转换为另一种,将以上闭包的//???这里不予解释,因为常玩汇编或C的小伙伴肯定早就了然于心鸟!

  9. Swift中使用C API时传递指针注意事项

    我们在Swift中可以使用大量C语言形式的系统API,这些API中有不少包含了指针参数,因此这篇博文将给大家介绍在于CAPI进行交互时,Swift2.2如何妥善处理指针的问题。在Apple官方的《UsingSwiftwithCocoaandObjective-C》一书中已经明确谈到——传递给函数的指针只有在函数调用期间才确保是有效的。由此可知,我们在Swift中尽量使用更上层的API,如果在C语言层涉及到函数回调等情况,也尽量使用Blocks。

  10. 指针 与 swift 中的引用

    一个Swift常量或者变量引用一个引用类型的实例与C语言中的指针类似,不同的是并不直接指向内存中的某个地址,而且也不要求你使用星号(*)来表明你在创建一个引用。Swift中这些引用与其它的常量或变量的定义方式相同。这意味两者适用不同的任务。有理由预计一个结构体实例在赋值或传递时,封装的数据将会被拷贝而不是被引用。任何在结构体中储存的值类型属性,也将会被拷贝,而不是被引用。

随机推荐

  1. 【cocos2d-x 3.x 学习笔记】对象内存管理

    Cocos2d-x的内存管理cocos2d-x中使用的是上面的引用计数来管理内存,但是又增加了一些自己的特色。cocos2d-x中通过Ref类来实现引用计数,所有需要实现内存自动回收的类都应该继承自Ref类。下面是Ref类的定义:在cocos2d-x中创建对象通常有两种方式:这两中方式的差异可以参见我另一篇博文“对象创建方式讨论”。在cocos2d-x中提倡使用第二种方式,为了避免误用第一种方式,一般将构造函数设为protected或private。参考资料:[1]cocos2d-x高级开发教程2.3节[

  2. 利用cocos2dx 3.2开发消灭星星六如何在cocos2dx中显示中文

    由于编码的不同,在cocos2dx中的Label控件中如果放入中文字,往往会出现乱码。为了方便使用,我把这个从文档中获取中文字的方法放在一个头文件里面Chinese.h这里的tex_vec是cocos2dx提供的一个保存文档内容的一个容器。这里给出ChineseWords,xml的格式再看看ChineseWord的实现Chinese.cpp就这样,以后在需要用到中文字的地方,就先include这个头文件然后调用ChineseWord函数,获取一串中文字符串。

  3. 利用cocos2dx 3.2开发消灭星星七关于星星的算法

    在前面,我们已经在GameLayer中利用随机数初始化了一个StarMatrix,如果还不知道怎么创建星星矩阵请回去看看而且我们也讲了整个游戏的触摸事件的派发了。

  4. cocos2dx3.x 新手打包APK注意事项!

    这个在编译的时候就可以发现了比较好弄这只是我遇到的,其他的以后遇到再补充吧。。。以前被这两个问题坑了好久

  5. 利用cocos2dx 3.2开发消灭星星八游戏的结束判断与数据控制

    如果你看完之前的,那么你基本已经拥有一个消灭星星游戏的雏形。开始把剩下的两两互不相连的星星消去。那么如何判断是GameOver还是进入下一关呢。。其实游戏数据贯穿整个游戏,包括星星消除的时候要加到获得分数上,消去剩下两两不相连的星星的时候的加分政策等,因此如果前面没有做这一块的,最好回去搞一搞。

  6. 利用cocos2dx 3.2开发消灭星星九为游戏添加一些特效

    needClear是一个flag,当游戏判断不能再继续后,这个flag变为true,开始消除剩下的星星clearSumTime是一个累加器ONE_CLEAR_TIME就是每颗星星消除的时间2.连击加分信息一般消除一次星星都会有连击信息和加多少分的信息。其实这些combo标签就是一张图片,也是通过控制其属性或者runAction来实现。源码ComboEffect.hComboEffect.cpp4.消除星星粒子效果消除星星时,为了实现星星爆裂散落的效果,使用了cocos2d提供的粒子特效引擎对于粒子特效不了

  7. 02 Cocos2D-x引擎win7环境搭建及创建项目

    官网有搭建的文章,直接转载记录。环境搭建:本文介绍如何搭建Cocos2d-x3.2版本的开发环境。项目创建:一、通过命令创建项目前面搭建好环境后,怎样创建自己的Cocos2d-x项目呢?先来看看Cocos2d-x3.2的目录吧这就是Cocos2d-x3.2的目录。输入cocosnew项目名–p包名–lcpp–d路径回车就创建成功了例如:成功后,找到这个项目打开proj.win32目录下的Hello.slnF5成功了。

  8. 利用cocos2dx 3.2开发消灭星星十为游戏添加音效项目源码分享

    一个游戏,声音也是非常的重要,其实cocos2dx里面的简单音效引擎的使用是非常简单的。我这里只不过是用一个类对所有的音效进行管理罢了。Audio.hAudio.cpp好了,本系列教程到此结束,第一次写教程如有不对请见谅或指教,谢谢大家。最后附上整个项目的源代码点击打开链接

  9. 03 Helloworld

    程序都有一个入口点,在C++就是main函数了,打开main.cpp,代码如下:123456789101112131415161718#include"main.h"#include"AppDelegate.h"#include"cocos2d.h"USING_NS_CC;intAPIENTRY_tWinMain{UNREFERENCED_ParaMETER;UNREFERENCED_ParaMETER;//createtheapplicationinstanceAppDelegateapp;return

  10. MenuItemImage*图标菜单创建注意事项

    学习cocos2dx,看的是cocos2d-x3.x手游开发实例详解,这本书错误一大把,本着探索求知勇于发现错误改正错误的精神,我跟着书上的例子一起调试,当学习到场景切换这个小节的时候,出了个错误,卡了我好几个小时。

返回
顶部