成员函数指针与回调函数

                                                                 成员函数指针与回调函数

       首先来提一个问题,函数能作为参数吗?也许你会疑惑,但它确实可以,Windows的回调函数就是这么一个东西,就是那个callback,当满足一定条件的时候就会调用这个回调函数,那怎么知道什么时候才满足这个条件呢?这个不用我们操心,系统会帮我们高效的检查,这个检查就是监听器的工作?有很多名词没听过?没关系,今天我讨论的主题不是这个。听过那最好啦!那么设置一个回调函数的时候,是不是有点烦,参数类型啊,参数个数啊,返回类型啊一定要一致,还要加一个callback声明,否则就会调用失败!!!切记!!!

       听起来,callback函数有点玄,当你条件满足的时候才去调用,所以很高效,那它是怎么实现的呢?考虑下面的代码:

typedef void (*ptrFn)(char);

ptrFn pFn;

char keyDown = 0;

void Function(charkey)

{

       switch(key)

       {

       case 'd':cout<<"Dwas pressed!Move Right!"<<endl;break;

       case 's':cout<<"Swas pressed!Move Down!"<<endl;break;

       case 'w':cout<<"Wwas Pressed!Move Up!"<<endl;break;

       case 'a':cout<<"Awas Pressed!Move Left!"<<endl;break;

       default:break;

       }

}

void SetCallBack()

{

       keyDown = getch();

       while(keyDown!= '0')

       {

              pFn(keyDown);

              keyDown = getch();

       }

}

void main()

{

       pFn = Function;

       SetCallBack();

}

       上面的代码不难理解,就是按下wasd来控制人物的移动,因为用的getch()函数读取一个字符(按下一个字符后,不需要按回车),要记得加入#include <conio.h>上面的几行代码有点回调函数的味道了,只是windows的回调函数比这个复杂多了,咱们先不讨论那个!

       先来理解下上面的代码,typedef void (*ptrFn)(char);typedef重命名函数指针,ptrFn指向的是一个空返回类型,参数为 char 的函数,然后我们要设置自己的回调函数的时候就可以这样写:

void 函数名 (char 参数名)

{

      //要执行的代码

}

然后在main()主函数里,将pFn = 函数名,这样就可以调用你设置的函数了!别看了,自己先去调试一下,理解好了再往下看!不然你又会迷迷糊糊的了!如果已经理解的同学,继续前进!

       那么我想将上面的回调函数放在类里面,作为成员函数来调用行不行呢?你马上会想到以下的代码:

class Game

{

private:

       floatx,y;

public:

       voidFunction(char key);

};

void Game::Function(charkey)

{

       switch(key)

       {

       case 'd':cout<<"Dwas pressed!Move Right!"<<endl;break;

       case 's':cout<<"Swas pressed!Move Down!"<<endl;break;

       case 'w':cout<<"Wwas Pressed!Move Up!"<<endl;break;

       case 'a':cout<<"Awas Pressed!Move Left!"<<endl;break;

       default:break;

       }

}

void main()

{

       Game game;

       pFn = game.Function;

       SetCallBack();

}

你会发现无法编译通过,说什么:无法从“void (__thiscall Game::* )(char)”转换为“ptrFn”!!!

这是为什么?理解一下错误信息,无法从(Gme::*)(char)转换为ptrFn,也就是说game.Function是Game::*类型的,而ptrFn必须指向的是void返回类型的,因为Function是classGame里面的东西,所以多了一个域的作用,而我们typedef void(*ptrFn)(char);的时候指明的是没有域作用的,也就是全局的,也就说“域”不匹配,当然无法编译通过!!!

那怎么办,既然“域”不匹配,那么我们就将它匹配行啦。那么指明匹配?typedef void (*ptrFn)(char);将这个改成:

typedef void (Game::*ptrFn)(char);这样?

我们发现这样还是不行,会出现一大堆的错误,就算这样能行,那么我们就一定得实例化一个对象,才能正常使用,而回调函数是不能通过实例化再来调用的。它必须得在程序运行的时候就存在了,而且我们也不可能改成这样typedef void (Game::*ptrFn)(char);如果这个是windows写的,那你怎么改?所以我们得另寻它法。

      匹配typedef的不行,那么只能匹配Game里面的了,那么怎么匹配,因为tepedef需要指向的全局的,那么怎么Game::Function改成全局的?其实不难,将它声明为静态的而且是public的就行了,这样的话,只要在使用Function的时候加个域说明Game::就行了,所以就有了下面的代码:

class Game

{

private:

       floatx,y;

public:

       static void Function(charkey);

};

void Game::Function(charkey)

{

       switch(key)

       {

       case 'd':cout<<"Dwas pressed!Move Right!"<<endl;break;

       case 's':cout<<"Swas pressed!Move Down!"<<endl;break;

       case 'w':cout<<"Wwas Pressed!Move Up!"<<endl;break;

       case 'a':cout<<"Awas Pressed!Move Left!"<<endl;break;

       default:break;

       }

}

 

 

void main()

{

       pFn = Game::Function;

       SetCallBack();

}

跟之前的代码没什么区别,只是在Game里的Function()加了一个static,

main()主函数里面加了一个域说明pFn = Game::Function;因为Game::Function()是静态的,所以不需要实例化一个对象,因为它程序一运行的时候已经被创建了。

      

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值