【转载】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之前,我们一般是这 ...
随机推荐
- 淘宝TOP之API测试
下面的文章,是很早之前写的.内容过时了.主要是获取session的方法,很简单了.作为一个中小型网站开发者,淘宝API的开放大大缩短了网站的开发周期和运作效率,面对海量的数据,开发者只要仔细阅读开发文 ...
- struts2从2.2.3升级到2.3.15.1步骤
1. 删除以下jar包 asm-3.1.jar asm-commons-3.1.jar commons-beanutils-1.7.0.jar commons-fileupload-1.2.2.jar ...
- 【转】使用Cocoapods创建私有podspec
Cocoapods是非常好用的一个iOS依赖管理工具,使用它可以方便的管理和更新项目中所使用到的第三方库,以及将自己的项目中的公共组件交由它去管理.Cocoapods的介绍及优点本文就不在赘述,我开始 ...
- 分布式Hadoop安装(二)
二.集群环境安装Zookeeper 1. hadoop0,namenode机器下,配置zookeeper,先解压安装包. 使用命令:tar -zxvf zookeeper-3.4.4. ...
- 从《BLAME!》说开去——新一代生产级卡通真实感混合的渲染方案
<BLAME!>是Polygon Pictures Inc.(以下简称PPI)创业33周年以来制作的第一部CG剧场电影,故事来自于贰瓶勉的同名漫画作品(中文译名为<探索者>或者 ...
- error while loading shared libraries: /usr/lib64/libc.so.6: invalid ELF header
在安装一个程序的时候提示libc.so.6过旧,但是查看libc.so的版本是最新的,于是尝试使用尝试软链接 ln -s /usr/lib64/libc.so /usr/lib64/libc.so. ...
- 解决genemotion模拟器冲突导致的Android Studio无法启动ADB的问题
首先命令行下运行 adb nodaemon server ./adb nodaemon server (Mac OSX) 如果出现错误: error: could not install *smart ...
- ASP.NET MVC路由规则
1 是从上往下寻找路由规则的 2 如果上面的匹配了,则下面的不会匹配 3 假如域名是www.startpress.cn 路由规则是 routes.MapRoute( name: "Defau ...
- [转] The program can't start because api-ms-win-crt-runtime-l1-1-0.dll is missing
https://www.smartftp.com/support/kb/the-program-cant-start-because-api-ms-win-crt-runtime-l1-1-0dll- ...
- 【html】button按钮的一些问题
问题: button 按钮在不设置 type 属性时,在不同的浏览器作用不一样.举个例子: html: <!doctype html> <html lang="en&quo ...