c/c++之函数指针

提起c++与c的指针与函数,如果不提函数指针,那么就对于c或c++的讨论是不完善的。与数据项类似的是,函数也有自己的地址,引用自《c++ primer plus》的一句话:“函数的地址是存储其机器语言代码的内存开始的地址”,而函数指针就是指向函数的指针。

有人会问,函数指针与普通的函数有什么不同呢?函数指针可以将函数的地址作为一个参数传进函数里。看到这里,人自然而然会问,直接在将函数返回值作为参数不是更好吗?虽然这种方法显得很笨拙,但是它允许在同一个函数里传递不同的函数地址,也就是说,它可以将不同功能的函数的地址传进函数里,进而让函数表示不同的内容。

例如:现在声明函数类型如下:

int add(int a,int b);
那么,如何用函数指针来表示呢
int (*p)(int a,int b);
可以看到,函数指针的表示只是把函数名换成了(*p)而已。切记,为保证优先级,*p必须用括号括起来。否则像这样:
int *p(int a,int b);
就会变成返回int类型指针的函数了。通常,要声明指向特定函数的指针,可以首先编写该函数的原型,然后用形如(*p)替换掉函数名即可。而(*p)也是函数,只是替代了函数名,因此,p则就成了指向函数的一个指针。

正如其它所有指针一样,声明后,需赋值,将函数的地址赋值给p:

p=add;

在这需提醒大家,和数组首地址为数组名一样,函数名即为函数的地址。而原型函数的特征标与返回值必须和指针函数一致。

               赋值给一个指针,那么理所当然的便可以通过一个指针来调用函数。来看下面代码:

int (*p)(int a,int b);
int   add(int a,int b);
p=add;
int x=add(1,2);
int y=(*p)(1,2);

实际上c++还允许这么使用p指针调用函数:

int y=p(1,2);


              为何(*p)与p在这里等价呢?引用《c++ primer plus》:一种学派认为,由于p是函数指针,而*p是函数,因此将(*p)作为函数的调用。另一种学派认为,由于函数名是指向该函数的指针,指向函数的指针应与函数名的行为相似,因此将p作为函数的调用。c++进行了折中处理。这两种方式都正确,或者至少是允许的。

下面来看看函数指针具体的实例:

#include<iostream>
using namespace std;
int add(int a)
{
	return a + 2;
}
int mul(int a)
{
	return a*2;
}
int test(int a, int(*p)(int))
{
	return p(a);
}
int main()
{
	int tet;
	cout << "Please input a number" << endl;
	cin >> tet;
	cout << "First:" <<test(tet, add) << endl;
	cout << "Second:" << test(tet, mul) << endl;
	system("pause");
	return 0;
}
结果为:




可以看到,定义add与mul两个函数,并把两个地址传进指针里,得到两个不同的结果。

             如果要使用多个函数,那么我们可以定义一个函数指针数组。比如:

int add(int a,int b);
int mul(int a,int b);
int sub(int a,int b);
int (*p[3])(int a,int b)={add,mul,sub};


为什么要把[3]的位置放在这个地方呢?因为[]运算符的优先级高于*,p先与[]结合,形成数组p[3],有三个元素的数组,再与*结合,表示此数组是指针类型的,每个数组元素相当于一个指针变量。如果读者需了解更多的指针知识,可参考我的另一篇博客《c++/c之指针》。

如何使用它们来调用函数呢?比如要获得指向int的值


int test=(*p[0])(1,2);

int test=p[0](1,2);

 这两种方式都行,取决于自己的爱好。下面通过一个具体的实例来理解:

#include<iostream>
using namespace std;
int add(int a)
{
	return a + 2;
}
int mul(int a)
{
	return a*2;
}
int sub(int a)
{
	return a - 2;
}
int(*p[3])(int a) = {add,mul,sub };
int main()
{
	int tet;
	
	cout << "Please input a number" << endl;
	cin >> tet;
	for (int i = 0; i < 3; i++)
	{
		cout <<"第" <<i+1<<"次:"<<p[i](tet) << endl;
	}
	system("pause");
	return 0;
}
运行结果为:



不知道学过c++和java的同学看到这有木有多态的既视感?这样写的好处就是减少了重复的代码,让代码更精简化。
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值