c/c++之函数指针

来源:互联网 发布:java 效率最高的排序 编辑:程序博客网 时间:2024/05/24 00:50

提起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的同学看到这有木有多态的既视感?这样写的好处就是减少了重复的代码,让代码更精简化。
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 淘宝卖韩国化妆品退货怎么办 去韩国留学手机怎么办 韩国办无线网怎么办 淘宝卖家被骗怎么办 淘宝买软件被骗怎么办 被淘宝店诈骗怎么办? 支付宝被骗2000怎么办 给私人打款后不发货怎么办 毕业证寄丢了怎么办 微商下单返现被骗一千四怎么办 淘宝买东西卡里多扣钱怎么办 付款了卖家不发货怎么办 淘宝客服不解决问题怎么办 淘宝未付款订单怎么办 淘宝被限制购买怎么办 苹果官换机维修过怎么办 iphone x官换机坏了怎么办 小娃不要大人睡怎么办? 深度睡眠太少怎么办 踏板摩托车淹缸怎么办 电喷摩托车淹缸怎么办 踏板摩托不过油怎么办 火花塞被汽油淹怎么办 踏板车淹缸了怎么办 电喷汽车淹缸怎么办 踏板摩托车粘缸怎么办 鬼火打不着火怎么办 踏板摩托车没电怎么办 买摩托车被骗了怎么办 鬼火电瓶坏了怎么办 摩托闷油了怎么办 鬼火发不着火怎么办 淘宝买东西发错货了怎么办 咸鱼售假处罚怎么办 趣头条登录不上怎么办 淘宝集运超租怎么办 淘宝发货多发了怎么办 小学生数学学不好怎么办 小学生不爱学英语怎么办 小学生基础知识没学好怎么办 小学生应用题学不明白怎么办