函数指针
与数据类似,函数也有地址。函数的地址是存储其机器语言代码的内存的开始地址。
函数指针的基础知识
- 获取函数的地址;
- 声明一个函数指针;
- 使用函数指针来调用函数。
1.获取函数的地址
获取函数的地址很简单:只要使用函数名(后面不跟参数)即可。eg.如果think()是一个函数,则think就是该函数的地址。要将函数作为参数进行传递,必须传递函数名。
process(think); //传递的参数是函数的地址
thought(think()); //传递的参数是函数的返回值
2.声明函数指针
声明指向某种类型的指针时,必须指定指针指向的类型。同样,声明指向函数的指针时,也必须指定指针指向的函数的类型。这意味着声明应指定函数的返回类型以及函数的参数列表。即声明应像函数原型那样指出有关函数的信息。
double pam(int); //函数原型
//指针类型声明:
double (*pf)(int); //pf指向使用一个int参数并返回double类型的函数
将pam替换为了(*pf)。由于pam是函数,因此(*pf)也是函数。则pf就是函数指针。
通常,要声明指向特定类型的函数的指针,可以先编写这种函数的原型,然后用(*pf)替换函数名,这样pf就是这类函数的指针。
括号不能省略:
double (*pf)(int); //pf指向一个返回double的函数
double *pf(int); //pf()是一个函数,返回double指针
正确的声明pf后,便可以将相应函数的地址赋给它:
double pam(int);
double (*pf)(int);
pf = pam; //pam()的参数类型和返回类型必须与pf相同,否则编译器将拒绝赋值
3.使用指针来调用函数
使用(*pf)时,只需将它看作函数名即可:
double pam(int);
double (*pf)(int);
pf = pam;
double x = pam(4);
double y = (*pf)(5);
实际上,C++也允许像使用函数名那样使用pf:
double y = pf(5);
函数指针示例
程序7.18
#include<iostream>
double betsy(int);
double pam(int);
void estimate(int lines, double (*pf)(int));
int main()
{
using namespace std;
int code;
cout << "How many lines of code do you need? ";
cin >> code;
cout << "Here's Betsy's estimate:\n";
estimate(code, betsy);
cout << "Here's Pam's estimate:\n";
estimate(code, pam);
system("pause");
return 0;
}
double betsy(int lns)
{
return 0.05 * lns;
}
double pam(int lns)
{
return 0.03 * lns + 0.0004 * lns * lns;
}
void estimate(int lines, double(*pf)(int))
{
using namespace std;
cout << lines << " lines will take ";
cout << (*pf)(lines) << " hour(s)\n";
}
深入探讨函数指针
程序7.19
#include <iostream>
const double * f1(const double ar[], int n);
const double * f2(const double[], int);
const double * f3(const double *, int);
int main()
{
using namespace std;
double av[3] = { 1112.3, 1542.6, 2227.9 };
//函数指针:
const double *(*p1)(const double *, int) = f1;
auto p2 = f2; //自动检测类型
//const double *(*p2)(const double *, int) = f2;
cout << "Using pointers to functions:\n";
cout << "Address Value\n";
cout << (*p1)(av, 3) << ": " << *(*p1)(av, 3) << endl;
cout << p2(av, 3) << ": " << *p2(av, 3) << endl;
//pa是一个指针数组
//auto不能用于列表初始化
const double *(*pa[3])(const double *, int) = { f1,f2,f3 };
//auto可以用于单值初始化
auto pb = pa;
//const double *(**pb)(const double *, int)=pa;
cout << "\nUsing an array of pointers to function:\n";
cout << " Address Value\n";
for (int i = 0; i < 3; i++)
cout << pa[i](av, 3) << ": " << *pa[i](av, 3) << endl;
cout << "\nUsing a pointer to a pointer to a function:\n";
cout << " Address Value\n";
for (int i = 0; i < 3; i++)
cout << pb[i](av, 3) << ": " << *pb[i](av, 3) << endl;
//一个指向函数指针数组的指针
cout << "\nUsing a pointer to an array of pointers:\n";
cout << " Address Value\n";
// 一种简单的声明方法:
auto pc = &pa;
//const double *(*(*pc)[3])(const double *, int) = &pa;
cout << (*pc)[0](av, 3) << ": " << *(*pc)[0](av, 3) << endl;
//复杂的声明:
const double *(*(*pd)[3])(const double *, int) = &pa;
//将返回值存储为pdb
const double * pdb = (*pd)[1](av, 3);
cout << pdb << ": " << *pdb << endl;
cout << (*(*pd)[2])(av, 3) << ": " << *(*(*pd)[2])(av, 3) << endl;
system("pause");
return 0;
}
const double * f1(const double * ar, int n)
{
return ar;
}
const double * f2(const double ar[], int n)
{
return ar + 1;
}
const double * f3(const double ar[], int n)
{
return ar + 2;
}