一 函数指针
就是指向函数的指针,指针指向特定的类型,函数的类型由它的返回类型和形参类型共同决定,与函数名无关。指针函数,简单的来说,就是一个返回指针的函数,其本质是一个函数,而该函数的返回值是一个指针。
bool func(const string &,const string &)
想要声明一个指向改函数的指针,只需要用指针特换函数名即可:
bool (*pf)(const string&, const string&); //未初始化
赋值的方法有两种:
pf=func;
pf=&func;
使用方法:
#include <cstdio>
#include <string>
#include <iostream>
using namespace std;
bool func(const string &str1, const string &str2)
{
cout << str1 << " and "<< str2 << endl;
return true;
}
int main()
{
string str1 = "hell0";
string str2 = "world";
func(str1, str2);
bool (*pf)(const string&, const string&);
pf = func;
cout << (void *)pf << endl;
printf("%p\n", pf);
pf(str1, str2);
pf = &func;
cout << (void *)pf << endl;
printf("%p\n", pf);
(*pf)(str1, str2);
return 0;
}
二 函数指针形参
虽然不能定义函数类型的形参,但是形参可以是指向函数的指针。此时,形参看起来是函数类型,实际上确实当成指针使用:
//第三个形参是函数类型,它会自动地转成指向函数类型的指针
void useBigger(const string &s1,const string &s2,bool pf(const string &,const string&));
//等价
void useBigger(const string &s1,const string &s2,bool (*pf)(const string&,const string&));
//使用方法
useBigger(s1,s2,func);
三 返回函数指针的函数
// c 形式
#include <stdio.h>
#include <stdlib.h>
void fun(int k, char c)
{
printf("this is fun2 call:%d %c\n", k, c);
}
//fun1 函数的参数为double,返回值为函数指针void(*)(int, char)
void (*fun1(double d))(int, char)
{
printf("%f\n",d);
return fun;
}
int main()
{
void (*p)(int, char) = fun1(3.33);
p(1, 'a');
return 0;
}
//c++ 形式
#include <iostream>
using namespace std;
class test
{
public:
int fun(int a, char c)
{
cout<<"this is fun call:"<<a<<" "<<c<<endl;
return a;
}
};
class test2
{
public:
// test2 的成员函数fun1,参数是double,
//返回值是test的成员函数指针int(test::*)(int, char)
int (test::*fun1(double d))(int, char)
{
cout<<d<<endl;
return &test::fun;
}
};
int main()
{
test mytest;
test2 mytest2;
int (test::*p)(int, char) = mytest2.fun1(3.33);
(mytest.*p)(1, 'a');
return 0;
}
四 函数指针别名
#include <stdio.h>
void e_g(int a)
{
printf("a=%d", a);
}
typedef void(*FIRST_FUNCTION)(int);
int main()
{
FIRST_FUNCTION p;
p = e_g;
p(888);
getchar();
return 0;
}
五 函数指针数组
char * (*pf[3])(char * p);
它是一个数组,数组名为pf,数组内存储了3个指向函数的指针。这些指针指向一些返回值类型为指向字符的指针、参数为一个指向字符的指针的函数。
六 特例
1 返回函数指针的函数声名
需求:1) 定义一个函数;2) 该函数具有以下特点,两个参数,返回值是函数指针,并且一个参数也是函数指针。假如返回值和参数函数指针同为void (*)(int);另一个函数参数是int型。该函数定义名称为my_func。
typedef void (*HANDLER)(int); // int 参数函数和返回函数定义
HANDLER my_func(int, HANDLER);
//若是不使用typedef,可以理解为:
void (*)(int) my_func(int, void (*)(int)); //没有这种写法
//故:
void (*(my_func)(int, void(*)(int)))(int)
void (*my_func(int, void(*)(int)))(int)
2 char (*(*f[3])())(char * p)
函数指针数组。
3 (*(void(*) ())0)()
《C Traps and Pitfalls》这本经典中的一个例子:
第一步:void() (),可以明白这是一个函数指针类型。这个函数没有参数,没有返回值。
第二步:(void() ())0,这是将0强制转换为函数指针类型,0是一个地址,也就是说一个函数存在首地址为0的一段区域内。
第三步:((void() ())0),这是取0地址开始的一段内存里面的内容,其内容就是保存在首地址为0的一段区域内的函数。
第四步:((void() ())0)(),这是函数调用。
4 函数指针数组的指针
char * (*(*pf)[3])(char * p);
函数指针数组的指针:f是一个指针,这个指针指向一个包含了3个元素的数组;这个数组里面存的是指向函数的指针;这些指针指向一些返回值类型为字符型的指针、行数为一个字符行指针的函数。
七 回调函数
回调函数是指使用者自己定义一个函数,实现这个函数的程序内容,然后把这个函数(入口地址)作为参数给调用者,由调用者在运行时来调用的函数。
回调允许函数调用者在运行时调整原始函数的行为。
回调的另一种用途在于处理信号量。例如一个POSIX程序可能在收到SIGTERM信号时不愿立即终止;为了保证一切运行良好,该程序可以将清理函数注册为SIGTERM信号对应的回调。
回调亦可以用于控制一个函数是否作为:Xlib允许自定义的谓词(NSPredicate)用于决定程序是否希望处理特定的事件。