篇一、函数指针
函数指针:是指向函数的指针变量,在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:
int operator()(int x){return x;}
};
A a;
a(5);

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

class Func{
public:
int operator() (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++敞开了一道天窗,但随之而来的便是一些复杂的问题和陷阱,如何去蔽扬利还需要我们不断学习和探索。

C++中的函数指针和函数对象总结的更多相关文章

  1. 函数指针玩得不熟,就不要自称为C语言高手(函数指针是解耦对象关系的最佳利器,还有signal)

    记得刚开始工作时,一位高手告诉我说,longjmp和setjmp玩得不熟,就不要自称为C语言高手.当时我半信半疑,为了让自己向高手方向迈进,还是花了一点时间去学习longjmp和setjmp的用法.后 ...

  2. c++入门之函数指针和函数对象

    函数指针可以方便我们调用函数,但采用函数对象,更能体现c++面向对象的程序特性.函数对象的本质:()运算符的重载.我们通过一段代码来感受函数指针和函数对象的使用: int AddFunc(int a, ...

  3. c++学习之初话 函数指针和函数对象 的因缘

    函数指针可以方便我们调用函数,但采用函数对象,更能体现c++面向对象的程序特性. 函数对象的本质:()运算符的重载.我们通过一段代码来感受函数指针和函数对象的使用: int AddFunc(int a ...

  4. Delphi 函数指针(函数可以当参数)

    首先学习: 指向非对象(一般的)函数/过程的函数指针 Pascal 中的过程类型与C语言中的函数指针相似,为了统一说法,以下称函数指针.函数指针的声明只需要参数列表:如果是函数,再加个返回值.例如声明 ...

  5. C#委托与C语言函数指针及函数指针数组

    C#委托与C语言函数指针及函数指针数组 在使用C#时总会为委托而感到疑惑,但现在总新温习了一遍C语言后,才真正理解的委托. 其实委托就类似于C/C++里的函数指针,在函数传参时传递的是函数指针,在调用 ...

  6. Day8 函数指针做函数参数

    课堂笔记 课程回顾         多态 virtual关键字 纯虚函数 virtual func() = 0;         提前布局vptr指针 面向接口编程 延迟绑定 多态的析构函数的虚函数. ...

  7. typedef void (*Fun) (void) 的理解——函数指针——typedef函数指针

    首先介绍大家比较熟悉的typedef int i;//定义一个整型变量i typedef myInt int: myInt j;//定义一个整型变量j 上面介绍得是我们常用的比较简单的typedef的 ...

  8. [C/C++]如何解读返回函数指针的函数声明

    今天在看<深入理解C++11>的时候,看到一段有意思的代码: int (*(*pf())())() { return nullptr; } 我立刻就懵了——从来没有见过这样的函数声明.那么 ...

  9. C/C++回调方式系列之一 函数指针和函数回调模式

    一.函数指针 1. 函数的定义 return_type function_name(parameter list) { function_body } return_type: 返回值,函数一定有返回 ...

  10. c语言的函数指针和函数指针数组的简单demo

    今天,简单记录一下,函数指针和函数指针数组的使用,废话不多说,直接贴上代码,里面有详细的注释,方便以后查阅. #include <cstdio> #include <Windows. ...

随机推荐

  1. 一行一行分析JQ源码学习笔记-06

    节点类型获取$("span")首先 判断 if(select.nodeType) markarray() 类数组 转化成真正的数组 var adiv = document.getE ...

  2. MVC3+EF4.1学习系列(一)-------创建EF4.1 code first的第一个实例

    基于EF4.1 code first 简单的CRUD  园子中已经有很多了 ~~ 真不想再写这个了 可是为了做一个完整的小demo 从开始 到后面的一些简单重构 还是决定认真把这个写出来 争取写些别人 ...

  3. 修改textField的placeholder的字体和颜色

    textField.placeholder = @"username is in here!"; [textField setValue:[UIColor redColor] fo ...

  4. 解决 .NET Core 中 GetHostAddressesAsync 引起的 EnyimMemcached 死锁问题

    在我们将站点从 ASP.NET + Windows 迁移至 ASP.NET Core + Linux 的过程中,目前遇到的最大障碍就是 —— 没有可用的支持 .NET Core 的 memcached ...

  5. dd if=/dev/zero of=的含义是什么?Linux 下的dd命令使用详解

    http://blog.sina.com.cn/s/blog_8b5bb24f01016y3o.html 一.dd命令的解释 dd:用指定大小的块拷贝一个文件,并在拷贝的同时进行指定的转换. 注意:指 ...

  6. Python笔记1-20151021

    一.字符串和字符编码 字符 ASCII Unicode UTF-8 A 01000001 00000000 01000001 01000001 中 x 01001110 00101101 111001 ...

  7. KVM 虚拟化基本搭建

    KVM虚拟化技术 KVM是基于x86架构上Linux操作系统的全虚拟化解决方案 ,在Centos6.3系统中,kvm已经被集成到内核中,相当于使用内核来做虚拟机管理程序.由于KVM本身就工作于内核环境 ...

  8. 与导航栏下控件的frame相关的edgesForExtendedLayout、translucent、extendedLayoutIncludesOpaqueBars、automaticallyAdjustsScrollViewInsets等几个属性的详解

    在引入了导航控制器UINavigationController和分栏控制器UITabBarController之后,我们在设置控件的frame的时候就需要注意避开导航栏UINavigationBar ...

  9. C# List 扩展排序

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Comm ...

  10. 转:java.io.IOException: Exceeeded maximum number of redirects: 5 解决版本

    Jmeter运行的时候出现的重定向超过n次的问题: When trying to test a Silverlight application, I get the below error. Has ...