在Cocos3.x版本中,对比之前的2.x版本,使用了很多C++11的新特性。std::function对象和std::bind机制就是其中一个。怎么把这两者联系起来呢,可以从Cocos3.x中的回调函数入手。在这之前,先来了解一下这两个的一些基础内容以及如何运作。1、std::function
std::function是一个函数对象类,所谓函数对象类,我们可以把它当作一种表示函数的数据类型,普通的数据类型是返回数据,而它是返回一个函数对象。
function的通常形式为 std::function<F( T1, T2, … ,TN)> ,表示它包装了一个具有类型为T1,T2...TN的N个参数,返回值类型为F的函数对象。它怎么运作的呢,举个例子:
std::function<float(int x, float y)>f; //声明函数对象f, 两个参数, 返回值为float
struct add{ //构造一个可以使用“()”进行调用的函数对象类型
float operator()(int x,float y)
{
return x + y;
};
};
f = add();
std::cout<<f(3 ,1.1);//函数对象调用
上面的例子中,我们把一个函数赋值给了一个std::function对象,然后通过函数对象来调用,这个对于回调函数十分有用,后面再说。
2、std::bind
std::bind()就是接受一个函数或者函数对象(跟std::function联系起来),然后通过绑定生成具有一个或多个参数的函数对象。通常形式为 std::bind(Func, args…) ,Func表示绑定的函数,args表示得到的函数对象所带有的参数。我们可以利用上面生成的函数对象f当作绑定的函数对象,传入std::bind中,举个例子:
auto ff1 = std::bind(f, 1 , 3.2); //绑定f()的两个参数
auto ff2 = std::bind(f, std::placeholders::_1 , 3.2);
auto ff3 = std::bind(f, std::placeholders::_1, std::placeholders::_2 );
std::cout<<ff1()<<std::endl;
std::cout<<ff2(1)<<std::endl;
std::cout<<ff3(1 ,3.2)<<std::endl;
std::placeholders::_1表示一个占位符对象,用于表示当函数f通过函数ff进行调用时,函数ff的第一个参数在函数f的参数列表中的位置。第一个参数称为” std::placeholders::_1″, 第二个参数为” std::placeholders::_2″,依此类推。
现在我们返回到Cocos的回调函数上,在HelloWorld中,看一下它的回调函数是怎么操作的:
首先是closeItem的创建:
auto
closeItem =
MenuItemImage::create
(
"CloseNormal.png" ,
"CloseSelected.png" ,
CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
"CloseNormal.png" ,
"CloseSelected.png" ,
CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
CC_CALLBACK_1函数定义则与std::bind联系起来:
#define CC_CALLBACK_1(__selector__,__target__, ...) std::bind(&__selector__,__target__, std::placeholders::_1, ##__VA_ARGS__)
MenuItemImage的create函数:
MenuItemImage
*
MenuItemImage::create(const
std::string& normalImage,
const
std::string& selectedImage,
const
ccMenuCallback& callback)
而回调参数ccMenuCallback则是用了std::function语法:
typedef
std::function<void(Ref*)> ccMenuCallback;
因此绕了一大圈其实就是
ccMenuCallback =
std::bind
(
&HelloWorld::menuCloseCallback, this
);
所以我们在创建closeItem也可以直接使用std::bind:
auto closeItem = MenuItemImage::create
(
"CloseNormal.png" ,
"CloseSelected.png",
"CloseNormal.png" ,
"CloseSelected.png",
std::bind(
&HelloWorld::menuCloseCallback, this))
;