linux社区爱心援助Linux认证系列教程业界动态站务新闻公司招聘网络学院网址大全LPI专题CISCO专题
设为首页
加入收藏
管理团队
JSP  
JAVA  
PERL  
 您的位置:首页 > 开发语言 > c/c++/c# >
栏目导栏
  php
  JSP
  ASP
  asp.net
  JAVA
  c/c++/c#
  perl
  JavaScript
  Basic
  Delphi
资料搜索
热门文章
·Windows/Linux下配置Eclipse+C
·c语言static与extern的用法
·VC++(Ctime日期函数)应用
·typedef struct和struct的区别
·C/C++对文件操作
·C常用算法程序实例-线性代数方
·C#发送Email邮件方法总结
·struct的初始化,拷贝及指针成
·C语言入门实例 switch使用
·c++二叉树实现源代码
·对初学者的建议:如何学习C语言
·C++ Builder 处理控件中的文本
·常用的BCB & Delphi 函数
·C++入门经典教程完全版01-引言
·C++ Builder 使用Canvas对象的
最新文章
·使用C/C++扩展Python
·C语言入门实例 switch使用
·在C#里实现DATAGRID的打印预览
·如何使用 Visual C# .NET 创建
·C#发送Email邮件方法总结
·一道C#面试题目引发的思考
·c语言艺术清屏
·c语言static与extern的用法
·大数的阶乘算法
·C#编码好习惯
·构造函数,复制构造函数
·typedef struct和struct的区别
·struct的初始化,拷贝及指针成
·超强的指针学习笔记推荐
·STL中erase方法对链表类容器的
Google
 
C/C++中函数指针的含义
[ 作者:  加入时间:2007-10-05 22:17:42  来自:Linux联盟收集整理 ]
函数存放在内存的代码区域内,它们同样有地址,我们如何能获得函数的地址呢? fatLinux联盟
fatLinux联盟
  如果我们有一个int test(int a)的函数,那么,它的地址就是函数的名字,这一点如同数组一样,数组的名字就是数组的起始地址。

定义一个指向函数的指针用如下的形式,以上面的test()为例:

int (*fp)(int a);//这里就定义了一个指向函数的指针

  函数指针不能绝对不能指向不同类型,或者是带不同形参的函数,在定义函数指针的时候我们很容易犯如下的错误。

int *fp(int a);//这里是错误的,因为按照结合性和优先级来看就是先和()结合,然后变成了一个返回整形指针的函数了,而不是函数指针,这一点尤其需要注意!

  下面我们来看一个具体的例子:

#include <iostreamfatLinux联盟
#include <stringfatLinux联盟
using namespace std;  fatLinux联盟
  fatLinux联盟
int test(int a);  fatLinux联盟
  fatLinux联盟
void main(int argc,charargv[])    fatLinux联盟
fatLinux联盟
    cout<<test<<endl;//显示函数地址  fatLinux联盟
    int (*fp)(int a);  fatLinux联盟
    fp=test;//将函数test的地址赋给函数学指针fp  fatLinux联盟
    cout<<fp(5)<<"|"<<(*fp)(10)<<endl;  fatLinux联盟
//上面的输出fp(5),这是标准c++的写法,(*fp)(10)这是兼容c语言的标准写法,两种同意,但注意区分,避免写的程序产生移植性问题!  fatLinux联盟
    cin.get();  fatLinux联盟
fatLinux联盟
  fatLinux联盟
int test(int a)  fatLinux联盟
fatLinux联盟
    return a;  fatLinux联盟
}

  typedef定义可以简化函数指针的定义,在定义一个的时候感觉不出来,但定义多了就知道方便了,上面的代码改写成如下的形式:

#include <iostreamfatLinux联盟
#include <stringfatLinux联盟
using namespace std;  fatLinux联盟
  fatLinux联盟
int test(int a);  fatLinux联盟
  fatLinux联盟
void main(int argc,charargv[])    fatLinux联盟
fatLinux联盟
    cout<<test<<endl;  fatLinux联盟
    typedef int (*fp)(int a);//注意,这里不是生命函数指针,而是定义一个函数指针的类型,这个类型是自己定义的,类型名为fp  fatLinux联盟
    fp fpi;//这里利用自己定义的类型名fp定义了一个fpi的函数指针!  fatLinux联盟
    fpi=test;  fatLinux联盟
    cout<<fpi(5)<<"|"<<(*fpi)(10)<<endl;  fatLinux联盟
    cin.get();  fatLinux联盟
fatLinux联盟
  fatLinux联盟
int test(int a)  fatLinux联盟
fatLinux联盟
    return a;  fatLinux联盟
}

函数指针同样是可以作为参数传递给函数的,下面我们看个例子,仔细阅读你将会发现它的用处,稍加推理可以很方便我们进行一些复杂的编程工作。

//-------------------该例以上一个例子作为基础稍加了修改-----------------------------  fatLinux联盟
#include <iostream>    fatLinux联盟
#include <string>    fatLinux联盟
using namespace std;    fatLinux联盟
    fatLinux联盟
int test(int);    fatLinux联盟
  fatLinux联盟
int test2(int (*ra)(int),int);  fatLinux联盟
  fatLinux联盟
void main(int argc,charargv[])      fatLinux联盟
{    fatLinux联盟
    cout<<test<<endl;  fatLinux联盟
    typedef int (*fp)(int);    fatLinux联盟
    fp fpi;  fatLinux联盟
    fpi=test;//fpi赋予test 函数的内存地址  fatLinux联盟
  fatLinux联盟
    cout<<test2(fpi,1)<<endl;//这里调用test2函数的时候,这里把fpi所存储的函数地址(test的函数地址)传递了给test2的第一个形参  fatLinux联盟
    cin.get();  fatLinux联盟
}    fatLinux联盟
    fatLinux联盟
int test(int a)  fatLinux联盟
{    fatLinux联盟
    return a-1;  fatLinux联盟
fatLinux联盟
  fatLinux联盟
int test2(int (*ra)(int),int b)//这里定义了一个名字为ra的函数指针  fatLinux联盟
fatLinux联盟
    int c=ra(10)+b;//在调用之后,ra已经指向fpi所指向的函数地址即test函数  fatLinux联盟
    return c;  fatLinux联盟
}

  利用函数指针,我们可以构成指针数组,更明确点的说法是构成指向函数的指针数组,这么说可能就容易理解的多了。

#include <iostream>    fatLinux联盟
#include <string>    fatLinux联盟
using namespace std;  fatLinux联盟
  fatLinux联盟
void t1(){cout<<"test1";}  fatLinux联盟
void t2(){cout<<"test2";}  fatLinux联盟
void t3(){cout<<"test3";}  fatLinux联盟
void main(int argc,charargv[])      fatLinux联盟
fatLinux联盟
    void* a[]={t1,t2,t3};  fatLinux联盟
    cout<<"比较t1()的内存地址和数组a[0]所存储的地址是否一致"<<t1<<"|"<<a[0]<<endl;  fatLinux联盟
  fatLinux联盟
    cout<<a[0]();//错误!指针数组是不能利用数组下标操作调用函数的  fatLinux联盟
  fatLinux联盟
    typedef void (*fp)();//自定义一个函数指针类型  fatLinux联盟
    fp b[]={t1,t2,t3}; //利用自定义类型fp把b[]定义趁一个指向函数的指针数组  fatLinux联盟
    b[0]();//现在利用指向函数的指针数组进行下标操作就可以进行函数的间接调用了;  fatLinux联盟
    cin.get();  fatLinux联盟
}

  仔细看上面的例子可能不用我多说大家也会知道是怎么一会事情了,最后我们做一个重点小结,只要记住这一点,对于理解利用函数指针构成数组进行函数间接调用就很容易了!

void* a[]={t1,t2,t3}; fatLinux联盟
cout<<"比较t1()的内存地址和数组a[0]所存储的地址是否一致"<<t1<<"|"<<a[0]<<endl; fatLinux联盟
fatLinux联盟
cout<<a[0]();//错误!指针数组是不能利用数组下标操作调用函数的

  上面的这一小段中的错误行,为什么不能这么调用呢? fatLinux联盟
fatLinux联盟
  前一篇教程我们已经说的很清楚了,不过在这里我们还是复习一下概念,指针数组元素所保存的只是一个内存地址,既然只是个内存地址就不可能进行a[0]()这样地址带括号的操作,而函数指针不同它是一个例外,函数指针只所以这么叫它就是因为它是指向函数指向内存的代码区的指针,它被系统授予允许与()括号操作的权利,进行间接的函数调用,既然函数指针允许这么操作,那么被定义成函数指针的数组就一定是可以一样的操作的。

Linux联盟收集整理 ,转贴请标明原始链接,如有任何疑问欢迎来本站Linux论坛讨论
评论】【加入收藏夹】【 】【打印】【关闭
※ 相关链接
 ·c/c++中结构体(struct)知识点强化,链表的学习  (2007-10-23 14:09:55)
 ·c/c++中结构体的入门教程  (2007-10-23 14:08:41)
 ·C/C++中命令行参数的原理  (2007-10-23 14:07:35)
 ·C/C++中利用空指针(NULL),提高程序运行效率  (2007-10-23 14:07:04)
 ·c/c++中的字符指针数组,指向指针的指针的含义  (2007-10-23 14:06:26)
 ·c/c++中字符串常量的不相等性,以及字符串的copy  (2007-10-23 14:05:52)
 ·C/C++中数组和指针类型的关系的入门教程  (2007-10-23 14:03:24)
 ·C/C++中枚举类型(enum)的入门教程  (2007-10-23 14:02:09)
 ·C/C++中多维数组的指针作为函数参数传递  (2007-10-23 14:00:11)
 ·c/c++关于多维数组指针变量  (2007-10-23 13:59:30)