一、函数名 与 &函数名
函数名就是函数的地址
void func(void) {
}
int main()
{
cout << func << endl;
cout << &func << endl;
return 0;
}
输出:
00D2142E
00D2142E
函数名 和 &函数名 的输出是一样的,但 &函数名 是什么?
void func() {
}
int main()
{
void (*fp)(void);
cout <<typeid(func).name() << endl;
cout<< typeid(&func).name()<<endl;
cout <<typeid(fp).name();
}
输出:
void __cdecl(void)
void (__cdecl*)(void)
void (__cdecl*)(void)
可以看到
- func的类型是void(void)
- &func的类型是 void(*)(void),与同类型的函数指针的类型相同
若把函数名看作是函数的地址,可以把 &函数名 看成是该类型的函数指针。
fp可以指向其他函数,并调用它
void func2() {
cout << "I'm func2";
}
int main()
{
void (*fp)(void);
fp = func2;
fp();
}
I'm func2
但很显然,&func并不是一个指针变量
所以,可以将 &函数名 看作为指向该 函数类型 的 函数指针类型
二、函数指针
1、声明
一般来说,声明指针时必须指定确定指向的类型,函数指针也是如此。当声明函数指针时,需要指定指向的函数类型,包括:
- 返回类型
- 参数列表
double (*fp)(int); //返回类型为double,参数为int类型
也可以用typedef
typedef double (*FP)(int); //FP是指向“返回值为double类型,参数为int类型”的一类函数的指针类型
FP fp; //声明一个此类指针
double cal(int); //函数声明
fp=cal; //指针赋值
2、函数指针调用函数
double (*fp)(int);
...
double result= (*fp)(5); //调用
3、作为函数参数传递
void myFunc(double (*fp)(int)); //函数指针作为参数传递
int sum(int a,int b) {
return a+b;
}
void myFunc(int a, int b, int (*fp)(int, int)) {
cout << (*fp)(a,b)<<endl;
}
int main()
{
myFunc(1,2, sum);
return 0;
}
输出:3
如果用typedef的话,程序的可读性会更好
typedef int (*FP)(int, int);
int sum(int a,int b) {
return a+b;
}
void myFunc(int a, int b, FP fp) {
cout << (*fp)(a,b)<<endl;
}
int main()
{
myFunc(1,2, sum);
return 0;
}
4、作为函数返回值
double (*fp)(int) myFunc(char* s); //函数返回类型为函数指针
以上写法是错误的!
正确的写法是
int (*myFunction(char* s))(int);
解释:
- myFunction是函数名
- 参数是
char* s
- 前后两个int说明该函数的返回类型是“参数为int,返回类型为int的函数指针”
int* (*myFunction(const char* s, int* (*fp)(void) ))(void) {
cout << s <<endl;
return fp;
}
int* func(void) {
cout << "I'm the returned function";
return NULL;
}
int* (*returnFp)(void);
int main()
{
returnFp =myFunction("So complicated.",func);
returnFp();
return 0;
}
输出:
So complicated.
I'm the returned function
但实际上 不建议 这样写!
如果用typedef代码会简单很多!
typedef int (*fp)(int);
fp myFunction(char* s); // function returning function pointer
5、函数指针数组
//以下四个函数的参数列表是等价的
const double* f1(const double arr[], int n);
const double* f2(const double* arr, int n);
const double* f3(const double [], int);
const double* f4(const double*, int);
const double* (*parray[4])(const double*, int)={f1,f2,f3,f4};
parray是一个函数指针数组
const double* f1(const double arr[], int n);
const double* f2(const double* arr, int n);
const double* f3(const double [] , int);
int main()
{
double arr[3] = {1.1,2.2,3.3};
const double* (*parray[3])(const double*, int) = { f1,f2,f3 };
cout << "Address0 : " << parray[0](arr, 0) << " — " << *(parray[0](arr, 0)) << endl;
cout << "Address1 : " << parray[1](arr, 0) << " — " << *(parray[1](arr, 0)) << endl;
cout << "Address2 : " << parray[2](arr, 0) << " — " << *(parray[2](arr, 0)) << endl;
return 0;
}
const double* f1(const double arr[], int n) {
return arr;
}
const double* f2(const double arr[], int n) {
return ++arr;
}
const double* f3(const double arr[], int n) {
return ++(++arr);
}
输出:
Address0 : 0055FB94 — 1.1
Address1 : 0055FB9C — 2.2
Address2 : 0055FBA4 — 3.3
使用typedef
typedef const double* (*PF)(const double [], int); // 将pf定义为一个类型名称
PF parray[3] = { f1,f2,f3 };
6、总结
适当使用 typedef 会让代码 简洁 且 可读性更高