【转载】C/C++ 函数指针 总结
转载自:http://blog.csdn.net/shihui512/article/details/9787125
什么是函数指针
函数指针的声明
函数指针的赋值
函数指针的使用
将函数作为其他函数的参数
在C类中使用函数指针
typedef 返回类型类名新类型参数表
函数指针的应用
用指向函数的指针作函数参数
函数指针与指针函数的区别
函数指针与typedef
函数指针与动态绑定
其他
什么是函数指针
就像某一变量的地址可以存储在相应的指针变量中一样,指向函数的指针中保存着函数代码起始处的地址
函数指针的声明
当声明一个函数指针时,必须声明它指向的函数类型。要指定函数类型,就要指出函数的返回类型和参数列表,如:
void (* pf)(int, int); //pf是一个函数指针,它指向的函数类型为:返回值为void,参数列表为(int, int)
函数指针的赋值
函数名本身即代表函数的地址,因此给函数赋值时可以不加&符号,如:
void func(char *);
void (* pf)(char *);
pf = func; //可以
pf = &func; //可以
函数指针的使用
一般来说,函数指针有以下两个用处:
调用函数
此时函数指针可看作函数的别名,如下面三条语句等价:
func("abc");
pf("abc"); //可以
(* pf)("abc"); //可以
将函数作为其他函数的参数
这是函数指针最普遍的用法,如:
void show(void (* pf)(char *), char * str); //第一个参数为函数指针
注意:函数指针实参可以指向不同函数,但这些函数类型(返回类型和参数列表)必须一样
使用函数指针作为函数参数的典型例子有库函数qsort( )
在C++类中使用函数指针
typedef 返回类型(类名::*新类型)(参数表)
- class CA
- {
- public:
- char lcFun(int a){ return; }
- };
- CA ca;
- typedef char (CA::*PTRFUN)(int);
- PTRFUN pFun;
- int main()
- {
- pFun = CA::lcFun;
- ca.(*pFun)(2);
- }
在这里,指针的定义与使用都加上了“类限制”或“对象”,用来指明指针指向的函数是那个类的这里的类对象也可以是使用new得到的。比如:
CA *pca = new CA;
pca->(*pFun)(2);
delete pca;
而且这个类对象指针可以是类内部成员变量,你甚至可以使用this指针。比如:
类CA有成员变量PTRFUN m_pfun;
void CA::lcFun2()
{
(this->*m_pFun)(2);
}
一句话,使用类成员函数指针必须有“->*”或“.*”的调用。
函数指针的应用
标准模板库中的sort排序
template<class RandomAccessIterator, class Predicate>
void sort(RandomAccessIterator first, RandomAccessIterator last, Predicate comp);
sort允许使用自己定义的比较函数(第三个参数)
// 比较分数
bool compareScore(const FightAttr& a, const FightAttr& b)
{
return a.score< b.score;
}
用指向函数的指针作函数参数
在C语言中,函数指针变量常见的用途之一是作为函数的参数,将函数名传给其他函数的形参。这样就可以在调用一个函数的过程中根据给定的不同实参调用不同的函数。
例如,利用这种方法可以编写一个求定积分的通用函数,用它分别求5个函数的定积分:每次需要求定积分的函数是不一样的。可以编写一个求定积分的通用函数integral,它有3个形参:
下限a上限b,以及指向函数的指针变量fun函数原型可写为
double integral (double a,double b,double (*fun)(double));
分别编写5个函数f1,f2,f3,f4,f5,
用来求上面5个函数的值。然后先后调用integral函数5次,每次调用时把a,b以及f1,f2,f3,f4,f5之一作为实参,即把上限、下限以及
有关函数的入口地址传送给形参fun,在执行integral函数过程中求出各函数定积分的值。
函数指针与指针函数的区别
1、函数指针
函数指针其实就是指向一个函数地址的指针,我们知道数值和函数一样都有自己的存在空间,也都有程序的首地址,数组名表示着整个数组代码占用内存的首地址,同理函数名也就是整个函数代码占用内存的首地址,函数指针就是指向函数占用内存的首地址,其定义格式如下:
type (*name)(参数列表);//函数返回值 (*函数指针)(参数列表)
例如我们可以定义一个函数返回值为int型的,参数列表为(int x)的函数,然后定义一个函数指针来指向他。
int func(int x);//定义函数
int (*f)(int x);//定义函数指针
f=func;//这样函数指针*f就指向函数func了
需要注意的是:函数指针的返回值和参数列表要和指向的函数的必须完全一样,这样才可以对其进行赋值。
2、指针函数
一个函数不仅可以带回一个整型数据的值,字符类型值和实型类型的值,还可以带回指针类型的数据,使其指向某个地址单元。
返回指针的函数,一般定义格式为:
类型标识符 *函数名(参数表)
int *f(x,y);
其中x,y是形式参数,f是函数名,调用后返回一个指向整型数据的地址指针。f(x,y)是函数,其值是指针。
如:char *ch();表示的就是一个返回字符型指针的函数。
函数指针与typedef
1、定义函数指针类型
// 定义一个原型为int Fun( int a );的函数指针
typedef int (*PTRFUN) ( int aPara );
2、函数指针变量的定义
PTRFUN pFun; // pFun 为函数指针变量名
int (*pFun2) ( int a ); // pFun2也是函数指针变量名
函数指针与动态绑定
// 获得函数指针的大小
unsigned psize = sizeof (void (*) ());
// 为函数指针声明类型定义
typedef void (*pfv) ();
pfv是一个函数指针,它指向的函数没有输入参数,返回类行为void。使用这个类型定义名可以隐藏复杂的函数指针语法。
指针变量应该有一个变量名:
void (*p) (); //p是指向某函数的指针
p是指向某函数的指针,该函数无输入参数,返回值的类型为void。左边圆括弧里星号后的就是指针变量名。有了指针变量便可以赋值,值的内容是署名匹配的函数名和返回类型。例如:
void func()
{
/* do something */
}
p = func;
p的赋值可以不同,但一定要是函数的地址,并且署名和返回类型相同。
传递回调函数的地址给调用者
现在可以将p传递给另一个函数(调用者)- caller(),它将调用p指向的函数,而此函数名是未知的:
void caller(void(*ptr)())
{
ptr(); /* 调用ptr指向的函数 */
}
void func();
int main()
{
p = func;
caller(p); /* 传递函数地址到调用者 */
}
如果赋了不同的值给p(不同函数地址),那么调用者将调用不同地址的函数。赋值可以发生在运行时,这样使你能实现动态绑定。
其他
1.总之,函数指针赋值时,&可加可不加;函数指针取值时(即作为函数别名进行调用时),*可加可不加
2.要注意带有返回值的函数,如:
func1(sqrt); //将函数地址作为参数传递
func2(sqrt(4.0)); //将函数返回值作为参数传递
区别在于函数名后跟不跟参数列表
example:
- void sort(int a[], int n); //sort函数
- void (*p)(int a[], int n) = NULL; //p就是指向void (int a[], int n)类型的函数指针
- p = sort; //函数名就是函数地址
- int arry[3] = {1, 2, 3};
- sort(arry, 3);
- p(arry, 3); //可以直接调用
【转载】C/C++ 函数指针 总结的更多相关文章
- C语言函数指针(转载)
二.通常的函数调用 一个通常的函数调用的例子:/* 自行包含头文件 */void MyFun(int x); /* 此处的声明也可写成:void MyFun(int) */int main(int a ...
- C++虚函数和函数指针一起使用
C++虚函数和函数指针一起使用,写起来有点麻烦. 下面贴出一份示例代码,可作参考.(需要支持C++11编译) #include <stdio.h> #include <list> ...
- 你必须知道的指针基础-7.void指针与函数指针
一.不能动的“地址”—void指针 1.1 void指针初探 void *表示一个“不知道类型”的指针,也就不知道从这个指针地址开始多少字节为一个数据.和用int表示指针异曲同工,只是更明确是“指针” ...
- C++基础——函数指针 函数指针数组
==================================声明================================== 本文版权归作者所有. 本文原创,转载必须在正文中显要地注明 ...
- Atitit java方法引用(Method References) 与c#委托与脚本语言js的函数指针
Atitit java方法引用(Method References) 与c#委托与脚本语言js的函数指针 1.1. java方法引用(Method References) 与c#委托与脚本语言js ...
- C语言函数指针的用法
函数指针是一种在C.C++.D语言.其他类 C 语言和Fortran 2003中的指针.函数指针可以像一般函数一样,用于调用函数.传递参数.在如 C 这样的语言中,通过提供一个简单的选取.执行函数的方 ...
- [转载]C++虚函数浅析
原文:http://glgjing.github.io/blog/2015/01/03/c-plus-plus-xu-han-shu-qian-xi/ 感谢:单刀土豆 C++虚函数浅析 JAN 3RD ...
- typedef定义函数类型或函数指针
转载请标明出处: 最近在看redis的代码,发现了有关函数指针的部分,想把它记下来. 在redis中有类似下面的定义,利用typedef 定义了一个新的类型,这种类型是一个函数: typedef vo ...
- 从cocos2dx中寻找函数指针传递的方法
目的 看到群里有个朋友搞了好几天函数指针传递,没搞好.所以写一篇文章,旨在从cocos2dx中帮朋友们找到如何传递指针. 旧版本的函数指针传递 全局函数函数指针调用 一般在C++11之前,我们一般是这 ...
随机推荐
- 《Xenogears》(异度装甲)隐含的原型与密码
<Xenogears>(异度装甲)隐含的原型与密码 X 彩虹按:一种高次元的“生命体”,因“事故”被抓来当成“超能源”,其实那不只是“无限的能源”而已,“它”是有意志的!在我们眼里看来,这 ...
- JavaScript 中数组实用浅析
本文适用于HTML.ASP 中的 JavaScript 脚本代码.代码以 HTML 中的 JS 为例,如果在 ASP 中,请将 document.write 改为 Response.Write 即可. ...
- WindowsPhone-GameBoy模拟器开发六--[转]指令系统实现必读:补码
网上有同行写了些好文章,在此就不现丑了,贴上连接,放在这里为了补充系列的完整性 计算机为什么选用二进制补码 为什么补码重要?因为计算机中内存.寄存器里面存的数都是用补码表示的!
- RPC 135端口
- 用eclipse建立servlet工程
1.打开eclipse,选择[文件]|[新建]|[项目] 2.选择[Tomcat Project]后单击下一步,输入项目名[TestTomcat],选择下一步,将[Can update contex ...
- Convert IPv6 Address to IP numbers (C#)
URL: http://lite.ip2location.com/ Use the code below to convert the IP address of your web visitors ...
- Codeforces Round #382 (Div. 2)B. Urbanization 贪心
B. Urbanization 题目链接 http://codeforces.com/contest/735/problem/B 题面 Local authorities have heard a l ...
- Android 5.0 Uicc框架分析
已同步更新至个人blog: dxjia.cn Uicc框架 UICC框架是Android在4.1引入的,使的对卡的管理控制更加清晰.要了解这个UICC框架,需要从UiccController开始, ...
- selenium 3.0发布
记得3年前selenium core team就放出风声selenium3.0将在某个圣诞节发布,然而大家等了3年,就在所有人都不再关注selenium进度的时候,selenium3.0 beta1悄 ...
- 在Windows 2008/2008 R2 上配置IIS 7.0/7.5 故障转移集群
本文主要是从:http://support.microsoft.com/kb/970759/zh-cn,直接转载,稍作修改裁剪而来,其中红色粗体部分,是我特别要说明的 若要配置 IIS 7.0 和 7 ...