美文网首页
C++仿函数

C++仿函数

作者: 克罗地亚催眠曲 | 来源:发表于2020-07-12 20:21 被阅读0次
仿函数

仿函数又称为函数对象,是一种能够行使函数功能的类,该类重载了operator()运算符,调用仿函数的时候实际上就是通过类对象调用重载后的operator操作符,重载operator()和重载普通的函数效果相同,当参数类型不同时会执行不同的代码逻辑。

仿函数使用

比如自定义了一个仿函数A

#include <typeinfo>
#include <iostream>
using namespace std;
class A{
public:
 int operator() (int a, int b){
    return a+b;
  }
 double operator() (double a, double b){
    return (a+b)*2;
  }
};
int main(){
  A a;
  auto c1 =  a(1, 2);
  cout << typeid(c1).name() << " " << c1 << endl;
  auto c2 = a(11.3, 2.4);
  cout << typeid(c2).name() << " " << c2 << endl;
}

C++标准库中的仿函数存在在于functional.h中,平时用到的最多的是greater,less这两个,这两个函数常被用做排序函数的参数。在排序函数中greater和less这两个函数可以被等效的lambda表达式替换。但是在优先队列中,不能直接使用lambda表达式替换。

所以才会接触到仿函数这个概念。优先队列自定义比较规则,可以使用仿函数或者对被比较的类重载小于操作符。由于C++规定操作符重载必须至少有一个类类型的操作数,因此当优先队列中的元素不是自定义类的时候,则没法对其重载小于操作符,此时只能实用仿函数来实现自定义的比较规则。
以下是为优先队列定义仿函数的示例

#include <iostream>
#include <queue>
#include <vector>
using namespace std;
class comp{
public:
  bool operator(const pair<int, int> &a, const pair<int,int> &b) {
    return a.second < b.second;
  }
};
int main(){
  priority_queue<pair<int,int>, vector<pair<int,int>>, comp> q;
  q.push({1,3});
  q.push({2,4});
  q.push({3,6});
  auto p = q.top();
  cout << p.first << " " << p.second << endl;
}
函数对象 vs 模板类型参数

很多人C++初学者会有这样的疑惑,在sort中可以使用lambda,而在优先队列的定义中不能使用,相反,在优先队列中可以使用仿函数,而在sort中则不能使用仿函数。

这个问题的根源在于没有分清楚仿函数(函数对象)和模板类型参数之间的关系。
sort函数的原型为

template <class RandomAccessIterator, class Compare>
  void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);

可以看到 comp是一个函数对象,因为lambda对象也属于函数对象,所以可以作为排序的参数。C++中凡是能够调用()运算符的就都是函数对象,包括函数、函数指针、重载了()运算符的对象,以及lambda对象。
优先队列的构造函数原型为

template<
    class T,
    class Container = std::vector<T>,
    class Compare = std::less<typename Container::value_type>
> class priority_queue;

填入尖括号中的应该是类型的名字,即typename,当然不能使用lambda作为typename,但是我们使用decltype来获得lambda的类型,作为typename,然后在构造函数的参数中把lambda示例传进去,就能work。
示例如下

#include<queue>
#include<iostream>
using namespace std;
int main(){
  auto comp = [](const pair<int,int> &a, const pair<int,int> &b){
    return a.second < b.second;
  };
  priority_queue<pair<int,int>, vector<pair<int,int>>, decltype(comp)> q(comp);
  q.push({1,3});  q.push({2,4});  q.push({3,6});
  auto p = q.top();
  cout << p.first << " " << p.second << endl;
}
参考文献
  1. https://www.cnblogs.com/64open/p/5267678.html

相关文章

  • Functor --- 仿函数

    仿函数(functors)在C++标准中采用的名称是函数对象(function objects),实际上就是函数对...

  • C++入门11 -- 仿函数,函数模版,类模版

    仿函数(函数对象) 仿函数:将一个对象当作一个函数来使用; 模版 泛型:将类型参数化以达到代码复用的技术,C++中...

  • C++仿函数

    仿函数 仿函数又称为函数对象,是一种能够行使函数功能的类,该类重载了operator()运算符,调用仿函数的时候实...

  • C++ 仿函数

    仿函数 定义:仿函数(functor),就是使一个类的使用看上去像一个函数。其实现就是类中实现一个operator...

  • C++11可调用对象包装器和绑定器

    可调用对象 在C++中,可以像函数一样调用的有:普通函数、类的静态成员、仿函数、lambda函数、类的成员函数、可...

  • C++ 中几种调用对象

    C++中一共有5种调用对象:函数,函数指针,重载了函数调用运算符的类(仿函数),bind创建的对象 和 lambd...

  • C++ 仿函数 举例

  • C++仿函数(functor)

    仿函数functor,就是使一个类的使用看上去象一个函数。其实现就是类中实现一个operator,这个类就有了类似...

  • 1.2 仿函数(function call操作符)

    从函数指针到仿函数。 1.1 函数调用操作符(C++语法中的左右括号)也可以被重载。 许多STL算法都提供了两个版...

  • windows逆向3

    VC 程序内存和编译的一些特征C++ 构造函数C++ 成员函数C++ 析构函数C++ 全局对象的构造C++ 全局对...

网友评论

      本文标题:C++仿函数

      本文链接:https://www.haomeiwen.com/subject/vyrncktx.html