函数对象适配器

原创 2018年04月16日 23:24:36
函数对象适配器是完成一些配接工作,这些配接包括绑定(bind),否定(negate),以及对一般函数或成员函数的修饰,使其成为函数对象,重点函数对象适配器(红色字体):
bind1st :将参数绑定为函数对象的第一个参数
bind2nd : 将参数绑定为函数对象的第二个参数
not1 :  对一元函数对象取反
not2 : 对二元函数对象取反

ptr_fun : 将普通函数修饰成函数对象
mem_fun : 修饰成员函数

mem_fun_ref : 修饰成员函数

bind1st与bind2nd

bind1st与bind2nd是绑定适配器,本例中,我们希望对MyPrint函数对象绑定参数:

//01仿函数适配器 bind1st bind2nd 绑定适配器

//绑定适配器需要继承binary_function,泛型分别是参数类型...最后一个是返回值类型
struct MyPrint :public binary_function<int, int, void>{
	void operator()(int v, int val)const{
		cout << "v:" << v << "val:" << val << endl;
		cout << v + val << " ";
	}

};
void test01(){
	vector<int> v;
	for (int i = 0; i < 10; i++){
		v.push_back(i);
	}
	
	//for_each(v.begin(), v.end(), MyPrint());//直接传入匿名对象也是可以的

	//绑定适配器 将一个二元的函数对象转换为一元函数对象
	int addNum = 200;
	for_each(v.begin(), v.end(), bind1st(MyPrint(),addNum));

}
注意 bind1st bind2nd的区别:(对于本例而言)
bind1st 将addNum绑定为函数对象的第一个参数

bind2nd 将addNum绑定为函数对象的第二个参数

not1 与not2 

not1 not2  取反适配器,本例中同样以0-9存入vector容器中,并且给出了自定义的排序方式,这是演示对二元谓词的取反操作,还有MyGreater5(返回比5 大的元素的迭代器),这是为了演示对一元谓词的取反操作:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<vector>
#include<algorithm>

#include<functional> //绑定适配器需要的头文件
using namespace std;

//仿函数适配器not1 not2  取反适配器

struct MyGreater5 : public unary_function<int,bool>{
	bool operator()(int v)const{
		return v > 5;
	}
};
struct MyPrint02{
	void operator()(int v){
		cout << v << " ";
	}
};
struct MyCompare :public binary_function<int,int,bool>{
	bool operator()(int v1, int v2) const {
		return v1 > v2;
	}
};
void test02(){
	vector<int> v;
	for (int i = 0; i < 10; i++){
		v.push_back(i);
	}
	for_each(v.begin(), v.end(), MyPrint02());
	cout << endl;
        //对二元谓词的取反操作
	sort(v.begin(), v.end(),not2(MyCompare()));
	for_each(v.begin(), v.end(), MyPrint02());
	cout << endl;

	vector<int>::iterator it = find_if(v.begin(), v.end(), MyGreater5());
	if (it == v.end()){
		cout << "未找到" << endl;
	}
	else{
		cout << *it << endl;
	}
	//对一元谓词取反
	it = find_if(v.begin(), v.end(), not1(MyGreater5()));
	if (it == v.end()){
		cout << "未找到" << endl;
	}
	else{
		cout << *it << endl;
	}

}
注意 not1和note2的区别
如果对二元谓词取反,就使用 not2

如果对一元谓词取反,就使用 not1

ptr_fun

个人理解为转化适配器,将普通函数转化为函数对象

//03仿函数适配器 ptr_fun
void MyPrint03(int val,int val2){
	cout << "val1:" << val << " val2:" << val2 << endl;;
}
void test03(){
	vector<int> v;
	for (int i = 0; i < 10; i++){
		v.push_back(i);
	}
	//for_each(v.begin(), v.end(), MyPrint03);
	//将普通函数转化为函数对象,这样就可以使用绑定适配器、取反适配器了
	for_each(v.begin(), v.end(),bind2nd( ptr_fun(MyPrint03),10));
}
mem_fun 与mem_fun_ref

成员函数适配器,如果我们容器中存储的是对象或者对象指针,使用成员函数适配器就能指定某个成员函数处理成员数据。

//04成员函数适配器 mem_fun mem_fun_ref
class Person{
public:
	Person(int age, int id){
		this->age = age;
		this->id = id;
	}
	void show(){  //假设这是对象数据的处理函数,展示自己的属性
		cout << "age:" << age << " id:" << id << endl;
	}
	int age;
	int id;
};
void test04(){
	//如果容器中存放的是对象或者对象指针,我们希望foreach算法打印的时候,调用类
	//自己提供的打印函数
	//存对象用mem_fun_ref适配器
	vector<Person> v;
	Person p1(1, 20), p2(2, 30), p3(3, 40), p4(4, 50); //创建对象
	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);

	//格式如下,不得不说STL的格式是真的奇怪!!!反正固定格式就这样了!!
	for_each(v.begin(), v.end(), mem_fun_ref(&Person::show));

	//存对象指针用mem_fun适配器
	vector<Person*> vp;
	vp.push_back(&p1);
	vp.push_back(&p2);
	vp.push_back(&p3);
	vp.push_back(&p4);
	for_each(vp.begin(), vp.end(), mem_fun(&Person::show));
}

注意 mem_fun 与 mem_fun_ref的区别:

mem_fun : 如果存储的是对象指针,需要使用mem_fun

mem_fun_ref : 如果存储的是对象,需要使用mem_fun_ref

总结一下:
如果希望函数对象适配器能对我们自己编写的函数对象有效,我们需要根据我们的函数对象类型继承STL的父类对象。
如果你本身是二元函数对象 ,则需要继承 
二元函数继承:public binary_function<参数类型,参数类型,返回类型>
一元函数继承:public unary_function<参数类型,返回类型>

还有别忘记继承之后的方法必须加const修饰以确保父类中函数的安全!!!

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_38032942/article/details/79968195

C++ STL/ (12) 函数对象适配器

我们在前一节介绍了函数对象的概念,本节介绍基于函数对象的一个概念–函数对象适配器。在讲函数对象适配器之前,我们来讲一讲普通函数,函数对象和函数对象适配器的关系。 普通函数是对程序功能的一种封装。这种...
  • anran_zhou
  • anran_zhou
  • 2017-04-11 15:08:01
  • 240

stl 容器适配器、迭代器适配器和函数适配器讲解

一、迭代器 list的迭代器不支持算术运算,也不支持关系运算符(=,>),他只提供前置和后置的自增、自减以及相等和不相等运算。list的内存不连续。 vector和deque容器的迭代器是一种类型...
  • SprintfWater
  • SprintfWater
  • 2013-04-07 20:59:56
  • 1607

STL的6大组件:容器、类属算法、迭代器、函数对象、适配器、分配器。

STL知识点。梗概。 ...
  • chenhu_doc
  • chenhu_doc
  • 2006-07-29 22:19:00
  • 3070

函数对象和谓词

在C++中,在应用程序运行阶段存在的所有实体都是对象,因此struct和class也可用作函数,这称为函数对象。注意,函数也可通过函数指针来调用,他们也是函数对象。     从概念上说,函数对象是用...
  • u010771437
  • u010771437
  • 2016-01-06 11:19:06
  • 559

stl算法设计理念_预定义函数对象和函数适配器2_案例

传智扫地僧课程学习笔记。 多看老师代码,多敲老师代码, class IsGreat { public: IsGreat(int i) { m_num = i; } bool o...
  • qq_18973645
  • qq_18973645
  • 2017-01-19 02:13:31
  • 69

STL-函数对象及函数对象适配器

一 函数对象Functor    STL中提供了一元和二元函数的两种Functor,通过unary_function和binary_function提供了这两种不同参数数量的Functor的基本结构,...
  • wulibin136
  • wulibin136
  • 2011-04-19 13:41:00
  • 390

STL函数对象及函数对象适配器

一 函数对象Functor 函数对象是重载了函数调用操作符的类的对象。因为这个对象重载了函数调用操作符,所以你可以像调用函数一样使用这个对象。 #include using namespace s...
  • chlele0105
  • chlele0105
  • 2013-08-18 17:14:58
  • 9302

函数对象及适配器

 定义了调用操作符的类,其对象常称作函数对象(function object),即它们的行为表现出类似于函数的行为。    函数对象通常用作泛型算法的实参,如标准库中大量泛型算法有需要函数对象的版本。...
  • xiantongyuan
  • xiantongyuan
  • 2007-10-23 11:18:00
  • 1603

C++模板库基础学习

  • 2011年12月09日 09:48
  • 9.09MB
  • 下载

c++stl简介

  • 2012年12月11日 17:10
  • 28KB
  • 下载
收藏助手
不良信息举报
您举报文章:函数对象适配器
举报原因:
原因补充:

(最多只允许输入30个字)