函数对象

首先我们看一下函数指针。

函数指针是指向函数的指针变量,在编译程序时,每一个函数都有一个入口地址,而指向这个函数的函数指针便指向这个地址。函数指针的作用主要有两个:用作调用函数和用作函数的参数。

函数指针用作调用函数的实例如下:

#include <iostream>
using namespace std;
typedef void (*PFT) ( char ,int );
void bar(char ch, int i)
{
    cout<<ch<<' '<<i<<endl;
}
int main()
{
    PFT pft;
    pft=bar;
    pft('e',91);
    return 0;
}

我们可以在一个函数的形参列表中传入一个函数指针,然后便可以在这个函数中使用该函数指针所指向的函数,这样可以使程序变得更加清晰和简洁。函数指针用作函数参数的实例如下:

#include <iostream>
using namespace std;
typedef void (*PFT) ( char ,int );
void bar(char ch, int i)
{
    cout<<ch<<' '<<i<<endl;
}
void func(char ch,int i,PFT pf)
{
    pf(ch,i);
}
int main()
{
    PFT pft;
    pft=bar;
    func('e',91,pft);
    return 0;
}

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

前面讲的是函数指针的应用,从一般的函数回调意义上来说,函数对象和函数指针是相同的,但是函数对象却具有许多函数指针所不具有的特点,从而使得程序设计更加灵活,而且能够实现函数的内联(inline)调用,使整个程序实现性能加速。

重载函数调用操作符的类,其对象常称为函数对象,即它们是行为类似函数的对象。一个类对象,表现出一个函数的特征,就是通过“对象名+(参数列表)”的方式来实现的,如果没有上下文,完全可以把它看作一个函数对待。这是通过重载类的operator()来实现的,如下:

#include <iostream>
using namespace std;
class A
{
public:
    int operator()(int x){return x;}
};
int main()
{
    A a;
    a(5);
    return 0;
}

这样a就成为一个函数对象,当我们执行a(5)时,实际上就是利用了重载运算符函数operator(),函数对象既然是一个类对象,那么我们当然可以在函数形参列表中调用它,它完全可以取代指针,如下:

#include <iostream>
using namespace std;
class Func
{
public:
    void operator()(int a ,int b)
    {
        cout<<a<<'+'<<b<<'='<<a+b<<endl;
    }
};
void addFunc(int a,int b,Func &func)
{
    func(a,b);
}
int main()
{
    Func func;
    addFunc(1,3,func);
    return 0;
}

上述例子中首先定义了一个函数对象类,并重载了operator()函数,然后在函数addFunc中的形参列表中使用这个类对象。

如果运用泛型思维来考虑,可以定义一个函数模板类,来实现一般类型的数据相加减等操作,如下:

#include <iostream>
using namespace std;
class Func
{
public:
    template<class T>
    void operator()(T a ,T b)
    {
        cout<<a<<'+'<<b<<'='<<a+b<<endl;
    }
};
template<class T>
void addFunc(T a,T b,Func &func)
{
    func(a,b);
}
int main()
{
    Func func;
    addFunc(1,3,func);
    addFunc(1.4,2.3,func);
    return 0;
}
原文地址:https://www.cnblogs.com/kevinq/p/4605981.html