温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

C++中的函数对象及函数适配器的功能

发布时间:2021-08-24 09:10:43 来源:亿速云 阅读:189 作者:chen 栏目:开发技术

这篇文章主要介绍“C++中的函数对象及函数适配器的功能”,在日常操作中,相信很多人在C++中的函数对象及函数适配器的功能问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++中的函数对象及函数适配器的功能”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

目录
  • 1 函数对象

  • 2 STL提供的函数对象

  • 3 函数适配器

  • 总结

1 函数对象

1.函数对象是行为类似函数的对象。一个类对象,表现出一个函数的特征,即通过对象名+(参数列表)的方式使用一个类对象。

2.使用STL中提供的或自定义的迭代器和**函数对象,**配合STL的算法,组合出各种各样的功能。

3.通过函数对象而不使用函数指针,可以增加通用性,提高效率。

4.函数对象概念:泛化的函数

C++中的函数对象及函数适配器的功能

①将普通函数作为函数对象:传递函数名

#include <iostream>
#include <numeric> //包含accumulate算法
#include <functional>
#include <vector>
using namespace std;
int mult(int a, int b) {
    return a * b;
}
int main()
{
    int a[] = { 1, 2, 3, 4, 5, 6, 7 };
    const int N = sizeof(a) / sizeof(int); //用该式确定数组长度,定义为常量
    cout << "所有数累乘为:" << accumulate(a, a + N, 1, mult) << endl; //将普通函数作为函数对象,传递函数名
    //指针a,a + N也可以作为迭代器
    return 0;
}

②将重载了()运算符的类的对象作为函数对象:传递"类名()"

#include <numeric>
#include <iostream>
using namespace std;
class MultClass {
public:
    int operator ()  (int a, int b) const {
        return a * b;
    }
};
int main()
{
    int a[] = { 1, 2, 3, 4, 5, 6, 7 };
    const int N = sizeof(a) / sizeof(int); //确定数组a的长度
    cout << "所有数乘积为:" << accumulate(a, a + N, 1, MultClass()) << endl; //传输方式是类名(),输出5040
    //指针a,a + N也可以作为迭代器
    MultClass ss;
    cout << ss(100, 100); //输出10000
    return 0;
}

2 STL提供的函数对象

C++中的函数对象及函数适配器的功能

1.系统提供函数对象帮助实现基本功能。

2.accmulate算法接受二元函数对象,transform算法接受一元函数对象。

①STL库的multiplies

#include <iostream>
#include <functional>
#include <numeric>
using namespace std;
int main(){
	int a[] = { 1, 2, 3, 4, 5, 6, 7 };
	const int N = sizeof(a) / sizeof(int);
	cout << accumulate(a, a + N, 1, multiplies<int>()) << endl;//通过STL自带的函数对象multiplies实现乘法,注意要写数据类型<int>
	//指针a,a + N也可以作为迭代器
	return 0;
}

②STL库的二元谓词greater

#include <iostream>
#include <algorithm>
#include <functional> //包含greater
using namespace std;
int main() {
	int arr[] = { 24, 43, 5, 4, 62, 34, 7654, 22 };
	const int N = sizeof(arr) / sizeof(int);
	copy(arr, arr + N, ostream_iterator<int>(cout, "\t"));
	cout << endl;
	sort(arr, arr + N, greater<int>()); //包含在<algorithm>中,默认是升序
	copy(arr, arr + N, ostream_iterator<int>(cout, "\t"));
	return 0;
}

3 函数适配器

适配器顾名思义,让函数适配算法。

Unary Predicate:一元谓词

binary:二元的

bind:结合,(使)联合在一起

C++中的函数对象及函数适配器的功能

C++中的函数对象及函数适配器的功能

①找出第一个大于40的数,注意用数组和vector都可以

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
using namespace std;
int main()
{
    int a[] = { 30, 40, 50, 90, 20, 10 };
    const int N = sizeof(a) / sizeof(int);
    int *c = find_if(a, a + N, bind2nd(greater<int>(), 40));
    cout << *c << endl;
    return 0;
}

一般使用数组初始化向量vector,后续操作更方便

int main()
{
    int a[] = { 30, 40, 50, 90, 20, 10 };
    const int N = sizeof(a) / sizeof(int);
    vector<int> v (a, a + N); //用数组初始化vector
    vector<int>::iterator p = find_if (v.begin(), v.end(), bind2nd(greater<int>(), 40) );
    if (p == v.end())
        cout << "找不到" << endl;
    else
        cout << *p << endl;
    return 0;
}
find_if算法在STL中的原型声明为:
template<class InputIterator, class UnaryPredicate>
InputIterator find_if(InputIterator first, InputIterator last, UnaryPredicate pred);
它的功能是查找数组[first, last)区间中第一个pred(x)为真的元素。
InputIterator、UnaryPredicate是用概念来做模板参数名

②利用prt_fun、not1、not2产生组合适配器

#include <iostream>
#include <functional>
#include <algorithm>
#include <vector>
using namespace std;
int g(int x, int y) { //实现类似greater的功能
    return x > y;
}
int main()
{
    int a[] = { 30, 90, 10, 23, 432, 656, 7, 78 };
    const int N = sizeof(a) / sizeof(int);
    vector<int> v(a, a + N);
    auto p1 = find_if(v.begin(), v.end(), bind2nd(ptr_fun(g), 40)); //找第一个大于40的数
    //ptr_fun将函数指针转换为函数对象,bind2nd将40作为二元函数对象的第二个参数
    if (p1 == v.end())
        cout << "no element" << endl;
    else
        cout << *p1 << endl;
    auto p2 = find_if(v.begin(), v.end(), not1(bind2nd(ptr_fun(g), 15))); //找第一个不大于15的数
    //not1对一元函数对象取逻辑反,find_if找到第一个令bind2nd取false的值
    if (p2 == v.end())
        cout << "no element" << endl;
    else
        cout << *p2 << endl;
    auto p3 = find_if(v.begin(), v.end(), bind2nd(not2(ptr_fun(g)), 15)); // 找第一个不大于15的数
    //not2对二元函数取逻辑反
    if (p3 == v.end())
        cout << "no element" << endl;
    else
        cout << *p3 << endl;
    return 0;
}

③成员函数适配器,类的成员函数要通过适配器转换为普通函数对象

#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
using namespace std;
struct Car
{
	int id;
	Car(int id) {
		this->id = id;
	}
	void display() const {
		cout << "car " << id << endl;
	}
};
int main() {
	vector<Car*> pcars;
	vector<Car> cars;
	for (int i = 0; i < 5; i++)
		pcars.push_back(new Car(i)); //push_back() 在Vector最后添加一个元素(参数为要插入的值)
	for (int i = 5; i < 10; i++)
		cars.push_back(Car(i));
	cout << "elements in pcars: " << endl;
	for_each(pcars.begin(), pcars.end(), mem_fun(&Car::display));//for_each算法对每一个迭代器范围中的元素进行函数对象计算
	//men_fun适配后函数对象的参数为"对象的指针"
	cout << endl;
	for_each(cars.begin(), cars.end(), mem_fun_ref(&Car::display));
	//men_fun_ptr适配后函数对象的参数为"对象的引用"
	cout << endl;
	for (size_t i = 0; i < pcars.size(); ++i)
		delete pcars[i];
	return 0;
}

为什么不能同全局函数一样直接传递函数名而成员函数必须以 &类名::函数名 的方式,因为需要考虑static成员函数的情况。
mem_fun(member适配为function):将成员函数适配为普通函数对象,适配出来的函数需要对象的指针作为参数。
men_fun_ref:将成员函数适配为普通函数对象,适配出来的函数需要对象的引用作为参数。

到此,关于“C++中的函数对象及函数适配器的功能”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

c++
AI