C/C++ 函数指针使用总结
一 函数指针介绍
函数指针指向某种特定类型,函数的类型由其参数及返回类型共同决定,与函数名无关。举例如下:
- int add(int nLeft,int nRight);//函数定义
该函数类型为int(int,int),要想声明一个指向该类函数的指针,只需用指针替换函数名即可:
- int (*pf)(int,int);//未初始化
则pf可指向int(int,int)类型的函数。pf前面有*,说明pf是指针,右侧是形参列表,表示pf指向的是函数,左侧为int,说明pf指向的函数返回值为int。则pf可指向int(int,int)类型的函数。而add类型为int(int,int),则pf可指向add函数。
- pf = add;//通过赋值使得函数指针指向某具体函数
注意:*pf两端的括号必不可少,否则若为如下定义:
- int *pf(int,int);//此时pf是一个返回值为int*的函数,而非函数指针
二 标准C函数指针
1函数指针的定义
1.1 普通函数指针定义
- int (*pf)(int,int);
1.2 使用typedef定义函数指针类型
- typedef int (*PF)(int,int);
- PF pf;//此时,为指向某种类型函数的函数指针类型,而不是具体指针,用它可定义具体指针</span>
2函数指针的普通使用
- pf = add;
- pf(100,100);//与其指向的函数用法无异
- (*pf)(100,100);//此处*pf两端括号必不可少
注意:add类型必须与pf可指向的函数类型完全匹配
3函数指针作为形参
- //第二个形参为函数类型,会自动转换为指向此类函数的指针
- Void fuc(int nValue,int pf(int,int));
- //等价的声明,显示的将形参定义为指向函数的指针
- Void fuc(int nValue,int (*pf)(int,int));
- Void fuc(int nValue,PF);
形参中有函数指针的函数调用,以fuc为例:
- pf = add;//pf是函数指针
- fuc(1,add);//add自动转换为函数指针
- fuc(1,pf);
4返回指向函数的指针
4.1 使用typedef定义的函数指针类型作为返回参数
- PF fuc2(int);//PF为函数指针类型
4.2 直接定义函数指针作为返回参数
- int (*fuc2(int))(int,int);//显示定义
说明:按照有内向外的顺序阅读此声明语句。fuc2有形参列表,则fuc2是一个函数,其形参为fuc2(int),fuc2前面有*,所以fuc2返回一个指针,指针本身也包含形参列表(int,int),因此指针指向函数,该函数的返回值为int.
总结:fuc2是一个函数,形参为(int),返回一个指向int(int,int)的函数指针。
二 C++函数指针
1由于C++完全兼容C,则C中可用的函数指针用法皆可用于C++
2 C++其他函数(指针)定义方式及使用
2.1 typedef与decltype组合定义函数类型
- typedef decltype(add) add2;
decltype返回函数类型,add2是与add相同类型的函数,不同的是add2是类型,而非具体函数。
使用方法:
- add2* pf;//pf指向add类型的函数指针,未初始化
2.2 typedef与decltype组合定义函数指针类型
- typedef decltype(add)* PF2;//PF2与1.1PF意义相同
- PF2 pf;// pf指向int(int,int)类型的函数指针,未初始化
2.3 使用推断类型关键字auto定义函数类型和函数指针
- auto pf = add;//pf可认为是add的别名(个人理解)
- auto *pf = add;//pf为指向add的指针
3函数指针形参
- typedef decltype(add) add2;
- typedef decltype(add)* PF2;
- void fuc2 (add2 add);//函数类型形参,调用自动转换为函数指针
- void fuc2 (PF2 add);//函数指针类型形参,传入对应函数(指针)即可
说明:不论形参声明的是函数类型:void fuc2 (add2 add);还是函数指针类型void
fuc2 (PF2 add);都可作为函数指针形参声明,在参数传入时,若传入函数名,则将其自动转换为函数指针。
4 返回指向函数的指针
4.1 使用auto关键字
auto fuc2(int)-> int(*)(int,int) //fuc2返回函数指针为int(*)(int,int)
4.2 使用decltype关键字
- decltype(add)* fuc2(int)//明确知道返回哪个函数,可用decltype关键字推断其函数类型,
5 成员函数指针
5.1普通成员函数指针使用举例
- class A//定义类A
- {
- private:
- int add(int nLeft, int nRight)
- {
- return (nLeft + nRight);
- }
- public:
- void fuc()
- {
- printf("Hello world\n");
- }
- };
- typedef void(A::*PF1)();//指针名前需加上类名限定
- PF1 pf1 = &A::fuc; //必须有&
- A a;//成员函数地址解引用必须附驻与某个对象地址,所以必须创建一个队形
- (a.*pf1)();//使用成员函数指针调用函数
5.2继承中的函数指针使用举例
- class A
- {
- public:
- void fuc()
- {
- printf("Hello fuc()\n");
- }
- void fuc2()
- {
- printf("Hello A::fuc2()\n");
- }
- };
- class B:public A
- {
- public:
- virtual void fuc2()
- {
- printf("Hello B::fuc2()\n");
- }
- };
- typedef void(A::*PF1)();
- typedef void(B::*PF2)();
- PF1 pf1 = &A::fuc;
- int main()
- {
- A a;
- B b;
- (a.*pf1)(); //调用A::fuc
- (b.*pf1)(); //调用A::fuc
- pf1 = &A::fuc2;
- (a.*pf1)(); //调用A::fuc2
- (b.*pf1)(); //调用A::fuc2
- PF2 pf2 = &A::fuc2;
- (b.*pf2)(); //调用A::fuc2
- }
6重载函数的指针
6.1 重载函数fuc
- Void fuc();
- Void fuc(int);
6.2 重载函数的函数指针
- void (*PF)(int) = fuc;//PF指向fuc(int)
- int(*pf2)(int) = fuc;//错误没有匹配的类型
注意:编译器通过指针类型决定选取那个函数,指针类型必须与重载函数中的一个精确匹配。
C/C++ 函数指针使用总结的更多相关文章
- C++虚函数和函数指针一起使用
C++虚函数和函数指针一起使用,写起来有点麻烦. 下面贴出一份示例代码,可作参考.(需要支持C++11编译) #include <stdio.h> #include <list> ...
- 为什么 C++ 中成员函数指针是 16 字节?
当我们讨论指针时,通常假设它是一种可以用 void * 指针来表示的东西,在 x86_64 平台下是 8 个字节大小.例如,下面是来自 维基百科中关于 x86_64 的文章 的摘录: Pushes a ...
- C++函数指针总结
学习c++的过程中,指针是难点,熟悉了指针之后,还有一个让人很蛋疼的难点,那就是函数指针了.本博文详细介绍一下常见的各种坑爹的函数指针. 至于指针的详细学习,推荐这篇博文C++指针详解 与数据一样,函 ...
- C与指针(结构体指针,函数指针,数组指针,指针数组)定义与使用
类型 普通指针 指针数组(非指针类型) 数组指针 结构体指针 函数指针 二重指针 定义方式 int *p; int *p[5]; int (*p)[5]; int a[3][5]; struct{.. ...
- 结构体内嵌函数指针实现C语言面向对象
结构体内嵌函数指针 #include<stdio.h> void say(int age) { printf("我%d岁了\n",age); } struct stud ...
- 用typedef定义函数指针的问题
在学习windows API的时候,遇到下面这段代码 以前见过的typedef的用法都是给一个数据类型取一个别名 typedef oldTypeName newTypeName 这种给数据类型 ...
- 你必须知道的指针基础-7.void指针与函数指针
一.不能动的“地址”—void指针 1.1 void指针初探 void *表示一个“不知道类型”的指针,也就不知道从这个指针地址开始多少字节为一个数据.和用int表示指针异曲同工,只是更明确是“指针” ...
- objective-c中的@selector()和 c /c++的函数指针
先看tomcat里用到的代码: //然后开始动画 //把图片放到animationImages,接受数组参数 self.tom.animationImages = arrayImage; //设置时间 ...
- C++基础——函数指针 函数指针数组
==================================声明================================== 本文版权归作者所有. 本文原创,转载必须在正文中显要地注明 ...
- QT中使用函数指针
想仿命令行,所以定义了一个类,让一个String 对应一个 function,将两者输入list容器. 类中定义了 QString commandStr; void (MainWindow::*com ...
随机推荐
- SQL Server百万级大数据量删除
删除一个表中的部分数据,数据量百万级. 一般delete from 表 delete from 表名 where 条件: 此操作可能导致,删除操作执行的时间长:日志文件急速增长: 针对此情况处理 de ...
- 【vue】vue全家桶
vue-router(http://router.vuejs.org) vuex(https://vuex.vuejs.org/zh/guide/) vue-resource(https://gith ...
- ELK的安装
首先得安装好Elasticsearch.Kibana和Logstash(这里全部使用rpm安装的是6.4.2版本,而且都是单机安装,暂时没有考虑分布式安装.) 服务器内存要求至少为4G,下图为运行起来 ...
- 洛谷 P1439 【模板】最长公共子序列
\[传送门啦\] 题目描述 给出\(1-n\)的两个排列\(P1\)和\(P2\),求它们的最长公共子序列. 输入输出格式 输入格式: 第一行是一个数\(n\), 接下来两行,每行为\(n\)个数,为 ...
- SkylineGlobe7.0.1版本 支持SQLite(*.sqlite;*.db)数据库
SQLite,是一款轻型的数据库,是遵守ACID的关联式数据库管理系统,它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了 ...
- MyBatis 传List参数 nested exception is org.apache.ibatis.binding.BindingException: Parameter 'idList' not found.
在MyBatis传入List参数时,MyBatis报错:nested exception is org.apache.ibatis.binding.BindingException: Paramete ...
- java list map set array 转换
1.list转set Set set = new HashSet(new ArrayList()); 2.set转list List list = new ArrayList(new HashSet( ...
- asp.net core Serilog的使用
先贴上关于使用这个日志组件的一些使用方法,等有时间了在吧官方的文档翻译一下吧,现在真是没时间. Serilog在使用上主要分为两大块: 第一块是主库,包括Serilog以及Serilog.AspNet ...
- 老婆大人 split,slice,splice,replace的用法
split()方法用于把一个字符串分割成字符串数组 str.split("字符串/正则表达式从该参数制定额地方分割str",可选,可指定返回数组的最大长度,如果没设置参数,整个字符 ...
- Android艺术——深看Activity的生命周期
探究Activity的生命周期 1.典型情况下的生命周期分析:onCreate 初始化工作,加载布局资源和数据:onStart ac正在启动但是无法交互,后台:onResume ac可见,显示在前台: ...