可调用对象

 

//仿函数是一个类的对象,这个对象 具有函数的功能 (函数对象)

 

 

bool MyComp(int x, int y)

{

    //return  x > y;

    return false;

}

 

template<typename T>

class _less

{

public:

    bool operator ()(T& a, T& b)

    {

        return a < b;

    }

};

 

void TestSort()

{

    list<int> iList({ 1, 4, 7, 8, 5, 3, 2, 9, 6 });

    list<int>::iterator it;

    //iList.sort();//对 iList进行升序排列

 

    //如果我们自己定义排序函数

    iList.sort(MyComp);// 变成了降序排列

 

    //我们的排序函数,其实是一个模板函数,有一个模板参数 _Pr 代表排序规则

    //我们要实现排序,无非是在里面判断  a[i] < a[j]

    //如果判断改成 a[i] > a[j] --》排序方式就变了

    //我们这个 a[i] < a[j] 在这个 sort函数里面,就调用了 _Pr(a[i], a[j])

    //--> sort 这个模板函数,_Pr 的默认值是 less<T>()

    //less<T>() 就是一个仿函数

    //-->less 是一个模板类  ---》less<T> 生成一个具体类

    //-->less<T>() 生成一个对象,这个对象,就是仿函数 (具有函数功能)

    //--》判断是否 a<b :  ret = less<int>()(a, b)

    //--》我们传入 一个函数指针或者仿函数  MyComp, 可以理解为我们重新定义了 < 符号

 

  

 

 

    //如果 MyComp 不写 return a > b 或者 a < b

    //我们分别写return true, return false

    //return true  --》出错

    //return false --》正常

    //我们之前讲过一个知识点:< 定义好了后, 所有的逻辑比较就都确定了

    //因为 >, >=, <=, ==, != 都可以用 < 符号表示出来

    // > 符号使用 < 符号表示出来:a > b  -->  我们可以写成  b < a

    // >=符号使用 < 符号表示出来:a >= b -->  我们可以写成  !(a < b)

    // <=符号使用 < 符号表示出来:a <= b -->  我们可以写成  !(b < a)

    // ==符号使用 < 符号表示出来:a == b -->  我们可以写出  !(a < b) && !(b < a)  [a既不大于b,也不小于b]

    // !=符号使用 < 符号表示出来:a != b -->  我们可以写成  (a < b) || (b < a)

 

    //接下来我们再看 MyComp(int x, int y) {return false;}

    // 也就是对 任意 x 和 y  ===> x < y 的结果都是 false

    // x,y 是任意的,把他们交换一下也成立 ==> y < x 也是false

    // 也就是对任意两个数 x ,y。x 既不大于y,也不小于y,==》 x == y

    // -->  也就 == 符号的推导,它的结果 恒为 true

    // --》 所以我们定义这个比较规则,就是说,我们定义所有数都相等

    // --》 所以 使用 return false 排序结果是 维持序列不变 (所有元素相等,已经排好序了)

 

    //再来看 MyComp(int x, int y) {return true;}

    //为什么会出错呢?

    //因为我们由这个可以推出 a!=a , 自相矛盾!

    // 我们看 != 符号的表示  (a < b) || (b < a) ==》恒为 true

    // 也就是 a != a 是 true

}

 

 

Lambda表达式和函数指针,仿函数一样是可以调用对象,写法为[z](cons int x){return x>z;};

[]里面是捕获参数分为值捕获和引用捕获,可以在lambda表达式内部使用,()里面的是参数列表,{}里面是函数体,

 

返回类型,如果只有一条return语句的话,则可以通过return语句来判断返回类型,如果有其他的语句都默认返回void,如果要返回正确的类型,则需要用尾置返回类型,例如[z](cons int x)->bool{return x>z;};对于find_if,count_if等这些的可调用对象只支持一个参数的,用函数的指针不如用lambda表达式方便,lambda可以捕获一个值作为它的比较对象;

 当需要在函数体内改变捕获的值则需要加mutable,例如[z]() mutable{return --z;};

 

Bind的绑定:auto newCallable=bind(callable,arg_list); newCallable本身是一个可调用对象,arg_list是一个逗号分隔的参数列表,对于callable的参数,它的参数有可能有占位符,如果有占位符需要用 using std::placeholders::_n , n为数字,例如

sort(iValue2.begin(), iValue2.end(),bind(Compare,_1,_2));

sort(iValue2.begin(), iValue2.end(),bind(Compare,_2,_1));

这两个是不同的排序,原因就是占位符,_1表示compare第一个参数,当前者sort调用A,B时,它会调用compare(A,B),而后者为compare(B,A);

当需要绑定引用参数的时候,需要用ref标准库函数,它的作用是返回一个对象,包含给定的引用,此对象可以拷贝,例如ostream对象的参数则需要用改函数。

posted @ 2017-02-06 09:41  菜鸟也有高飞的时候  阅读(263)  评论(0编辑  收藏  举报