原文:http://www.cnblogs.com/lvpengms/archive/2011/02/21/1960078.html

篇一、函数指针
函数指针:是指向函数的指针变量,在C编译时,每一个函数都有一个入口地址,那么这个指向这个函数的函数指针便指向这个地址。
函数指针的用途是很大的,主要有两个作用:用作调用函数和做函数的参数。
函数指针的声明方法
数据类型标志符 (指针变量名) (形参列表);
一般函数的声明为: 
int func ( int x );
而一个函数指针的声明方法为:
int (*func) (int x);
前面的那个(*func)中括号是必要的,这会告诉编译器我们声明的是函数指针而不是声明一个具有返回型为指针的函数,后面的形参要视这个函数指针所指向的函数形参而定。
然而这样声明我们有时觉得非常繁琐,于是typedef可以派上用场了,我们也可以这样声明:
typedef int (*PF) (int x);
PF pf;
这样pf便是一个函数指针,方便了许多。当要使用函数指针来调用函数时,func(x)或者  (*fucn)(x) 就可以了,当然,函数指针也可以指向被重载的函数,编译器会为我们区分这些重载的函数从而使函数指针指向正确的函数。
例子:

typedef void (*PFT) ( char ,int );void bar(char ch, int i){    cout<<"bar "<<ch<<''<<i<<endl;return ;}PFT pft;pft = bar;pft('e',91);


例子中函数指针pft指向了一个已经声明的函数bar(),然后通过pft来实现输出字符和整型的目的。
函数指针另一个作用便是作为函数的参数,我们可以在一个函数的形参列表中传入一个函数指针,然后便可以在这个函数中使用这个函数指针所指向的函数,这样便可以使程序变得更加清晰和简洁,而且这种用途技巧可以帮助我们解决很多棘手的问题,使用很小的代价就可获得足够大的利益(速度+复杂度)。

typedef void (*PFT) ( char ,int );void bar(char ch, int i){    cout<<"bar "<<ch<<''<<i<<endl;return ;}void foo(char ch, int i, PFT pf){    pf(ch,i);return ;}PFT pft;pft = bar;foo('e',12,pft);


上述例子我们首先利用一个函数指针pft指向bar(),然后在foo()函数中使用pft指针来调用bar(),实现目的。将这个特点稍加利用,我们就可以构造出强大的程序,只需要同样的foo函数便可以实现对不同bar函数的调用。

篇二、函数对象
前面是函数指针的应用,从一般的函数回调意义上来说,函数对象和函数指针是相同的,但是函数对象却具有许多函数指针不具有的有点,函数对象使程序设计更加灵活,而且能够实现函数的内联(inline)调用,使整个程序实现性能加速。
函数对象:这里已经说明了这是一个对象,而且实际上只是这个对象具有的函数的某些功能,我们才称之为函数对象,意义很贴切,如果一个对象具有了某个函数的功能,我们变可以称之为函数对象。
如何使对象具有函数功能呢,很简单,只需要为这个对象的操作符()进行重载就可以了,如下:

class A{public:intoperator()(int x){return x;}};A a;a(5);


这样a就成为一个函数对象,当我们执行a(5)时,实际上就是利用了重载符号()。
函数对象既然是一个“类对象”,那么我们当然可以在函数形参列表中调用它,它完全可以取代函数指针!如果说指针是C的标志,类是C++特有的,那么我们也可以说指针函数和函数对象之间的关系也是同前者一样的!(虽然有些严密)。当我们想在形参列表中调用某个函数时,可以先声明一个具有这种函数功能的函数对象,然后在形参中使用这个对象,他所作的功能和函数指针所作的功能是相同的,而且更加安全。
下面是一个例子:

class Func{public:intoperator() (int a, int b)    {        cout<<a<<'+'<<b<<'='<<a+b<<endl;return a;    }};int addFunc(int a, int b, Func& func){    func(a,b);return a;}Func func;addFunc(1,3,func);


上述例子中首先定义了一个函数对象类,并重载了()操作符,目的是使前两个参数相加并输出,然后在addFunc中的形参列表中使用这个类对象,从而实现两数相加的功能。
如果运用泛型思维来考虑,可以定一个函数模板类,来实现一般类型的数据的相加:

class FuncT{public:    template<typename T>    T operator() (T t1, T t2)    {        cout<<t1<<'+'<<t2<<'='<<t1+t2<<endl;return t1;    }};template <typename T>T addFuncT(T t1, T t2, FuncT& funct){    funct(t1,t2);return t1;}FuncT funct;addFuncT(2,4,funct);addFuncT(1.4,2.3,funct);


大名鼎鼎的STL中便广泛的运用了这项技术,详细内容可参见候捷大师的一些泛型技术的书籍,不要以为函数对象的频繁调用会使程序性能大大折扣,大量事实和实验证明,正确使用函数对象的程序要比其他程序性能快很多!所以掌握并熟练运用函数对象才能为我们的程序加分,否则.......
如此看来,函数对象又为C++敞开了一道天窗,但随之而来的便是一些复杂的问题和陷阱,如何去蔽扬利还需要我们不断学习和探索。

转载于:https://www.cnblogs.com/Leo-Forest/p/3153873.html

C++函数指针和仿函数【转】相关推荐

  1. boost源码剖析之:泛型函数指针类boost::function(rev#3)

    boost源码剖析之:泛型函数指针类boost::function(rev#3) 刘未鹏 C++的罗浮宫(http://blog.csdn.net/pongba)   Note: 并非新作,03年曾放 ...

  2. 函数指针amp;绑定: boost::functoin/std::function/bind

    see link: https://isocpp.org/wiki/faq/pointers-to-members function vs template: http://stackoverflow ...

  3. 【C/C 】浅谈C/C 中函数指针与回调函数

    01.函数指针 1.1.函数指针定义 一个函数总是占用一段连续的内存区域,函数名在表达式中有时也会被转换为该函数所在内存区域的首地址,这和数组名非常类似.我们可以把函数的这个首地址(或称入口地址)赋予 ...

  4. C++:函数指针进阶(三):Lambda函数详解

    1:Lambda函数语法 C++ 语法的基本格式为: [capture](parameters) -> return_type { /* ... */ } (1) [capture] :[]内为 ...

  5. STL算法——函数对象(仿函数)

    全部案例链接 https://download.csdn.net/download/weixin_45525272/12536637 1 函数对象 重载函数调用操作符的类,其对象常称为函数对象(fun ...

  6. C++函数指针、函数对象与C++11 function对象对比分析

    1.函数指针 函数指针:是指向函数的指针变量,在C编译时,每一个函数都有一个入口地址,那么这个指向这个函数的函数指针便指向这个地址.函数指针主要由以下两方面的用途:调用函数和用作函数参数. 函数指针的 ...

  7. 函数指针与 std::function 简介

    ​ 在c/c++实际编程中,使用函数指针/function对象有时候可以让我们的代码更加简洁条理,尤其存在对同一对象多种不同的处理方案时,使用函数指针/function对象结合std::map等数据结 ...

  8. c/c++中的函数指针和指针函数

    定义 1.指针函数,本质是函数,返回值为指针,形如,int *pfun(int, int),由于"*"的优先级低于"()"的优先级,所以等同于int *(pfu ...

  9. 0709 C语言常见误区----------函数指针问题

    1.函数指针的定义 对于函数 void test(int a, int b){ // } 其函数指针类型是void (* ) (int , int), 注意这里第一个括号不能少, 定义一个函数指针,v ...

  10. java跨函数跳转_C语言中将绝对地址转换为函数指针以及跳转到内存指定位置处执行的技巧...

    1.方法一 要对绝对地址0x100000赋值,我们可以用 (unsigned int  * ) 0x100000 = 1234; 那么要是想让程序跳转到绝对地址是0x100000去执行,应该怎么做? ...

最新文章

  1. NRPE实现对其它(远端)设备的监控
  2. 真机IOS8.3以上的文件夹共享
  3. NodeJS中form上传附件中针对表单的multiple attribute出现的问题总结
  4. 【算法】一个简单的K近邻(KNN)原理
  5. 十大经典排序算法之快速排序及其优化
  6. java 超时集合_确定性监视器脉冲/等待并在 生产环境 者 - 消费者集合中实现超时...
  7. java中 静态方法与成员方法何时使用
  8. 8步教你打开Android之门 NDK入门教程
  9. vue3使用vite创建项目【2分钟】
  10. 分组聚合查询两门以上MySQL_MySQL中的分组聚合查询
  11. Sql Server 分区
  12. [转载]Qlist的用法
  13. 在Globalscape EFT FTP服务器上安装SSL证书的方法
  14. 可以测试英语发音的软件,检测英语发音的软件
  15. 计算机小喇叭找不到,如何解决电脑右下角的小喇叭不见了的问题
  16. Python selenium 简单的实现大麦网自动购票过程
  17. Linux(Centos7)日志管理
  18. html banner广告代码,jquery实现的Banner广告收缩效果代码
  19. Encountered a duplicated sql alias [NAME] during auto-discovery of a native-sql query
  20. 2022 年前面试总结与感悟分享

热门文章

  1. 比Redis快50倍的中间件,为啥这么快?
  2. 不用找了,基于 Redis 的分布式锁实战来了
  3. 2019年失业以后,他们都经历了什么?
  4. 推荐 :深度学习初学者不可不知的25个术语和概念(上)
  5. dubbo yml配置_Dubbo常见配置说明
  6. jq ‘’操作‘’伪元素
  7. 4G手机网络通信是如何被黑客远程劫持的?
  8. javac无效问题解决
  9. 【图文】在windows7 下安装和配置Memcached 64-bit for Windows
  10. MPICH2在WINDOWS下的安装配置