要点

函数对象

重载了()的对象,和函数一个概念,但用对象来管理,可以有自己的状态什么的。

是用来代替 c 里的函数指针的.

准确的讲叫指向函数的泛化指针.

函数对象可以用

函数指针;
另1个相同函数调用的函数对象;
lambda;

如果类里需要持有 1 个函数指针,就可以用函数对象:

typedef std::function<int(const Sth & a)> callFunction;

class A{
private:
    callFunction cb;
}

lambda

lambda 可以等价为一个函数对象:

struct Compare {
        int operator()(cosnt int a, const int b){
                return a >= b;
        }
}

sort(begin(w),end(w),[](const int a, const int b){return a>=b;});
//和上面一致
sort(begin(w),end(w),Compare());

标准库函数对象

#include<functional>.

Screenshot from 2019-05-29 16-22-22-b9bc19a8-585b-443b-9d54-b8297a66d695

算术、运算、和逻辑,用在 algorithm 里,免得自己写:

sort(begin(w),end(w),greater<string>());

如果需要自己版本的标准库函数对象,就特例化1个:

template<> greater<A>::operator() {
        return A.val > A.val;
}

例子:

#include <iostream>
#include <functional>


void test_3(int a, int b, int c){
        std::cout << a << " Bind " << b << std::endl;
}

void test(int a, int b){
        std::cout << a << " Global function " << b << std::endl;
}

struct A {
        void test(int a, int b){
                std::cout << a << " Member Function " << b << std::endl;
        }
};


int main()
{
        std::function<void (int,int)> f1 = test;

        std::function<void (int,int)> f2(test);

        std::function<void (int,int)> f3 = [](int a, int b){
                std::cout << a << " Lamba  Function " << b << std::endl;
                return 100;
        };

        A a;

        //需要bind配合,返回1个function obj;
        using namespace std::placeholders;
        //bind函数
        std::function<void (int,int)> f4 = std::bind(test_3,_1,_2,0);

        //bind成员函数
        std::function<void (int,int)> f5 = std::bind(&A::test,a,_1,_2);

        f1(0,0);
        f2(0,0);
        f3(0,0);
        f4(0,0);
        f5(0,0);

        return 0;
}

可调用对象与 function 类模板

可调用对象: 函数、函数指针、函数对象、lamdba、bind 返回的函数对象.

不同的可调用对象共享相同的调用形式,如int (int,int);

可能希望建立个函数表,可以把不同调用对象都放进来:

map<string ,int(*)(int,int)> function_maps;
function_maps.insert({"+", add});
mod = Mod(); //函数对象
//添加失败,因为类型不匹配
function_maps.insert({"%", mod}) ;

为解决上面的类型不兼容,但是调用形式又相同的情况,c++11 定义了 function 模板类. Screenshot from 2019-05-29 16-34-07-dda7afe6-47d2-40f6-b57a-538270f2b4f1

function<int(int,int)> f;
f1 = add;
f2 = divide();
f3 = [](int i,int j){return i / j};
map<string, function<int(int,int)>) new_maps;//真正好用的函数表map

//初始化
new_maps["+"] = add;
new_maps["%"] = divide();
new_maps["/"] = f3;

//使用
new_maps["+"](1,2); //1+2