大家好,我是不会编程的程序猿,下面我将分享C++中的一个重要知识点,回调函数的理解和应用。
指针是一个用来指向内存地址的变量。程序运行时,与程序运行相关的所有变量或函数都需要加载内存,这就决定了程序运行时所有变量或函数都可以用指针来加载。函数是存放在内存代码区域内的,它们同样有地址,因此可以用指针来调用函数,我们把这种指向函数入口地址的指针称为函数指针。
int add(int nLeft,int nRight);//定义一个add函数
int (*pf)(int,int);//定义一个函数指针,*pf两侧的括号必须得加,否则会产生歧义
pf = add;//通过给函数指针赋值,使得其指向具体函数。
/*函数指针的应用*/
1.(*pf)(10,20);//函数指针的普通调用,与函数调用无异
2.void func(int nValue,int (*pf)(int,int))//函数指针做参数
3.int (*fuc2(int))(int,int);//函数指针做返回值
//说明:按照有内向外的顺序阅读此声明语句。fuc2有形参列表,则fuc2是一个函数,其形参为fuc2(int),fuc2前面有*,所以fuc2返回一个指针,指针本身也包含形参列表(int,int),因此指针指向函数,该函数的返回值为int.
注意:
1.声明函数指针时,只要函数返回值类型、参数个数、参数类型等保持一致,就可以声明一个函数指针;
2.函数指针必须用括号括起来(*pf)
实际应用过程中,通常使用宏定义的方式来声明函数指针,示例如下:
typedef void (*FP)(char* s);
void Invoke(char* s);
int main(int argc,char* argv[])
{
FP fp; //用宏FP来声明一个函数指针fp
fp=func;
fp("Hello World!\n");
return 0;
}
void func(char* s)
{
printf(s);
}
回调函数:就是定义并实现一个函数,然后把这个函数的指针作为参数传给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。简单来说,就是由别人的函数运行期间来回调你实现的函数。
回调函数的机制:
1、定义一个函数(普通函数即可);
2、将此函数的地址注册给调用者;
3、特定的事件或条件发生时,调用者使用函数指针调用回调函数。
普通回调函数1:
#include
void printWelcome(int len)
{
printf("welcome -- %d\n", len);
}
void printGoodbye(int len)
{
printf("byebye-- %d\n", len);
}
void callback(int times, void (* print)(int))
{
int i;
for (i = 0; i < times; ++i)
{
print(i);
}
printf("\n welcome or byebye !\n");
}
void main(void)
{
callback(10, printWelcome);
callback(10, printGoodbye);
}
普通回调函数2:
#include
typedef int(*callback)(int,int);
int add(int a,int b,callback p)//宏定义的方式声明函数指针p
{
return (*p)(a,b);
}
int add(int a,int b)
{
return a+b;
}
int main(int argc,char *args[])
{
int res = add(4,2,add);
printf("%d\n",res);
return 0;
}
普通回调函数3:
//定义带参回调函数
void PrintfText(char* s)
{
printf(s);
}
//定义实现带参回调函数的"调用函数"
void CallPrintfText(void (*callfuct)(char*),char* s)
{
callfuct(s);
}
//在main函数中实现带参的函数回调
int main(int argc,char* argv[])
{
CallPrintfText(PrintfText,"Hello World!\n");
return 0;
}
#include
#include
using namespace std;
using namespace std::placeholders;
typedef std::function<void(int,int)> Fun;
class B
{
public:
void call(int a,Fun f)
{
f(a,2);
}
};
class Test
{
public:
void callback(int a,int b)
{
cout<<a<<"+"<<b<<"="<<a+b<<endl;
}
void bind()
{
Fun fun=std::bind(&Test::callback,this,_1,_2);
B b;
b.call(1,fun);
}
};
int main()
{
Test test;
test.bind();
return 0;
}
本例中
bind函数
一般常用语法是: newFunction=bind(oldFunction,arg_list);
bind函数返回一个新的函数对象。其中bind第一个参数是oldFunction,它是待绑定的函数名,arg_list是oldFunction的参数列表。注意,这个参数列表是旧函数的参数列表,前面提到,返回的是子函数。我们可以随便给子函数定几个参数,但是肯定不能多于bind所绑定的原函数的参数个数。
举个例子:
//g是一个有两个参数的可调用对象
auto g=bind(f,a,b,_2,c,_1);
//其中f是具有5个参数的函数
//当我们调用g(x,y)时,实际调用的是f(a,b,y,c,x)
上面出现的_1,_2是它的占位符,bind最多可以使用9个占位符。这个占位符命名在std的placeholders中,使用时,要使用using std::placeholders.
function函数
function是一个函数对象的“容器”。
如function