项目中用到了很多封装在struct中的函数指针,以前在MFC里面经常用到则个作为回调函数,还以为是微软设计的特色呢。在网上查了一下它的用法,做个总结。
函数指针这种避免命名冲突上的额外好处对于一些库函数的编写者是很有意义的,因为库可能被很多的用户在许多不同的环境下使用,这样就能有效的避免冲突而保证库的可用性。
一般的时候用不到,主要还是一个简化结构和程序通用性的问题,也是实现面向对象编程的一种途径。简单的总结为:
1. 实现面向对象编程中的多态性
2. 回调函数
举两个例子:
1. 你现在要实现一个文件系统,但是文件的介质有硬盘和软盘,那么它们各自的读写函数实现肯定是不一样的。
好比
int a_write(char *data_stream, int LBA);
int b_write(char *data_stream, int LBA);
有一个结构体维护:
typedef int (*write_operation)(char* data, int LBA);
struct {
write_operation op;
...
} file_struct;
最后有一个写函数:
int file_wirte(char *data_stream, int LBA)
{
return file_struct.op(data_stream, LBA);
}
2. Windows编程中的事件handle函数,即回调函数,在事件队列都是一个函数指针来保存的:
typedef void (*event_handler) (unsigned int para1, unsigned int para2);
struct event {
unsigned int ev_id;
event_handler handler;
};
struct event event_queue[MAX_EVENT_SIZE];
程序可以通过扫描这个事件队列来获取每个事件对应的处理函数,然后调用它,即为回调函数。
使用函数指针的好处在于,可以将实现同一功能的多个模块统一起来标识,这样一来更 容易后期的维护,系统结构更加清晰。或者归纳为:便于分层设计、利于系统抽象、降低耦合度以及使接口与实现分开 我是初学者,不明白这段话什么意思,求解释
你上面那一段话,对于初学者来说确实坑爹,说的像什么官方话语,我看着也就只能理解个模糊大概。 先给你举个例子吧,函数指针的写法 int *p; int a; p=&a; //这是一般整型指针 #include <iostream> using namespace std; int arr(int a,int b){return 0;}//比如说是函数1 int brr(int a,int b){return 1;}//比如说是函数2 int main() { int (*frr)(int,int); //这里就是函数指针 frr =arr; //它可以指向arr cout<<frr(1,2)<<endl; frr=brr;//也可以指向brr,只需要改改指向的对象,就可以操作不同的函数 cout<<frr(1,2)<<endl; return 0; }
qincheng2007 |来自团队美女也开源吧 |七级采纳率49%
擅长:C/C++
好吧,假设你已经知道函数指针的写法和用法。 那么那段话的意思就是, 你有了一只手,可以用来装备并切换武器打怪,比如可以装备刀子,或者装备棍子。当你的武器只有一种或者比较少的时候,可能这只手切换武器的功能不常用到。当到了后期,你的武器多了,那你因为有了这只能装备并切换武器的手,而可以更有效率的打怪。 OVER
上面的话是有道理的。只是,要真的体会这些名词,需要你亲历躬行,一个“百度知道”是很难让你真正体会并理解的。国人一些教科书也不负责任,人云亦云的说这些话,但很少能透彻讲解。我小试一下。 1. 便于分层设计:函数指针是引用,是间接层,或曰隔离层。它输出到上层,给上层用户用。函数实体是实现,在下层,给开发者用,实现者(188金博宝bet师)关注。这就是简单的分层的概念了。上层用户想让一个函数所做的东西会变化时,我们只需要改变底层实现,并用函数指针指向新的实现就行了。 再精炼一下分层:分层的核心是对接口进行设计和实现。函数指针的作用就是提供不同实现的统一接口。 2. 利于系统抽象:只有存在多个类似的实体需要模拟、操作或控制时(这种情况很多)才需要抽象。多个类似的实体就是对象,抽象的结果就是类。在C里边,可以用函数指针数组完成这种抽象。如, fopen 就是一个例子。他可以打开文件。C里面将磁盘文件、串口、USB等诸多设备抽象为文件。 3. 降低耦合度以及使接口与实现分开:第1条中的解释已经说明了这一点。 再具体一下: 我曾搭建过一个嵌入式平台。其中的设备操作(硬件驱动)采用了多组函数指针数据,并进行了简单的封装,其结果是: 业务软件使用函数指针数组的封装函数访问设备。这个封装可展示为: int DevOpen(char *strDevName); int Write(int DevID, char* DataFrom, int StartDevAddr, int DataLong); int Read(int DevID, char* DataTo, int StartDevAddr, int DataLong); int DevClose(int DevID); 这组抽象出来的函数,是一组语义清晰且稳定的上层接口,为上层的业务开发团队使用。底层的驱动层,各自实现自己的设备打开、读、写及关闭代码,然后,注册自己的设备到系统列表里。上层业务接可以使用了。期间的耦合在这里: int Write(int DevID, char* DataFrom, int StartDevAddr, int DataLong) { /* Error detecting. */ return DevWrite[ DevID ]( char* DataFrom, int StartDevAddr, int DataLong ); } 其中,DevWrite[ DevID ]就是一个函数指针数组: int (*DevWrite)[ MAX_DEV_NUM ]( char*,int,int ) = {0}; 里面放的就是多个设备的写的操作。其中包括:UART,RTC,WatchDog。EEPROM,DigitalInput,DigitalOutput,Key,LCD,LED。 好了。说的太多了。如需要学习,可邮件livefuture@163.com。 但愿对你有所帮助。
书上给了个例子,但还是看不懂有什么好处? #include<stdio.h> float add(float x,float y) {return (x+y);} float sub(float x,float y) {return (x-y);} float mul(float x,float y) {return (x*y);} float div(float x,float y) {return (x/y);} float result(float x,float y,float(*pf)(float,float)) { float s; s=(*pf)(x,y); return s; } void main() { float a,b,s; char op; printf(""please select your operation (input +,-,*or/)\n"); scanf("%c",&op); printf("please input the two operand\n"); scanf("%f %f",&a,&b); switch(op) { case '+':s=result(a,b,add);break; case '-':s=result(a,b,sub);break; case '*':s=result(a,b,mul);break; case '/':s=result(a,b,div);break; } printf("the operation is :%f%c%f=%f\n",a,op,b,s); }
灵活。 实际上我觉得如果作参数不用指针的话,还真不知道怎么解决。 参数传递一般就是传值和传址两种方式,作为函数的话,好像都想不出怎么传值。 我理解所谓指向函数的指针就是这个函数的入口地址。直接就跳转到那个地址去执行了。
本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。