天天看点

C++11中的bind绑定器和function函数对象

绑定器和函数对象

    • bind1st/bind2nd简单用法
    • bind1st/bind2nd底层实现
    • function函数保留类型
    • function应用

bind1st/bind2nd简单用法

#include <iostream>
#include <vector>
#include <algorithm>
#include<functional>
#include <ctime>
using namespace std;

/*
	绑定器和函数对象(对象有小括号运算符重载函数)

	1.C++ STL中的绑定器
		bind1st	把函数对象operator()第一个参数 绑定成一个确定的值
		bind2nd	把函数对象operator()第二个参数 绑定成一个确定的值
	2.bind 绑定器 和function函数对象机制 C++11从boost库中引入的机制
	3.lambda 表达式 底层依赖函数对象机制实现
*/

template<typename Container>
void showContainer(Container conn)
{
	//使用typename告知Container作用域后面是一个类型 而不是变量
	//类型可以定义变量 但是变量本身不能定义变量
	typename Container::iterator it = conn.begin();

	for (; it != conn.end(); ++it)
	{
		cout << *it << " ";
	}
	cout << endl;

}


int main()
{
	vector<int> vec;
	srand(time(nullptr));
	for (int i = 0; i < 20; ++i)
	{
		vec.push_back(rand() % 100 + 1);
	}
	//泛型算法sort 默认从小到大排序 传入起始末尾迭代器
	showContainer(vec);
	sort(vec.begin(), vec.end());
	showContainer(vec);

	//great 是一个二元函数对象 小括号运算符重载函数有两个对象
	sort(vec.begin(), vec.end(), greater<int>());

	//将70按照顺序插入到容器当中 找第一个小于70的元素,从容器中拿一个数和70进行比较
	//operator()(const &val)
	//greater a > b
	//less	a < b
	//绑定器 + 二元函数对象 = 间接变成了一元函数对象
	//bind1st:bool operator()(const _Ty& _Left, const _Ty& _Right) 
	//		  bool operator()(70, const _Ty& _Right)
	//bind2nd
	auto it1 = find_if(vec.begin(), vec.end(), bind1st(greater<int>(), 70));
	auto it2 = find_if(vec.begin(), vec.end(), bind1st(less<int>(), 70));
	if (it1 != vec.end())
	{
		vec.insert(it1, 70);
	}
	return 0;
}
           

bind1st/bind2nd底层实现

template<typename Iterator, typename Compare>
Iterator my_find_it(Iterator first, Iterator last, Compare comp)
{
	for (; first != last; ++first)
	{
		//comp.operator()(*first)
		if (comp(*first))
		{
			return first;
		}
	}
	return last;
}

template<typename Compare,typename T>
class _mybind1st
{
public:
	_mybind1st(Compare comp, T val)
		:_comp(comp)
		, _val(val)
	{

	}
	bool operator()(const T& second)
	{
		return _comp(_val, second);
	}
private:
	Compare _comp;
	T _val;
};

//mybind1st (greater<int>(),70)
template<typename Compare , typename T>
_mybind1st<Compare,T> mybind1st(Compare comp, const T& val)
{
	//直接使用函数模板,好处是,可以进行推演
	//根据实参,推演出函数对象和元素类型推演出来
	return _mybind1st<Compare, T>(comp, T);
}
           

function函数保留类型

#include <iostream>
#include <vector>
#include <algorithm>
#include<functional>	//使用function函数对象类型
#include <ctime>
#include <string.h>
using namespace std;

/*
	bind 绑定器和函数对象
	C++ STL bind1st/bind2nd 本身还是一个函数对象

	function:绑定器,函数对象,lambda表达式 他们只能使用在一条语句中
*/
void hello1()
{
	cout << "hello world" << endl;
}

void hello2(string str)
{
	cout << str << endl;
}

int sum(int a, int b)
{
	return a + b;
}

class Test
{
public:
	//调用普通函数和成员函数方法的一大区别
	//调用普通的函数只需要函数名,但是调用成员方法需要依赖对象,this指针

	//函数指针 void (*pfunc)(string str)
	//成员方法 void (Test::*pfunc)(string str)
	void hello(string str)
	{
		cout << hello << endl;
	}
private:

};

int main()
{
	/*
	1.通过函数类型实例化function
	2.通过function调用operator()函数的时候,需要根据函数类型传入相应的参数
	*/
	//function的类模板定义处,看到希望用函数类型实例化类模板function
	//void(*)() 指向一个返回值为void,不带形参的函数
	//函数类型 只给出返回值和参数列表

	//用函数对象类型 把函数类型保留下来
	//func1.operator() 再调用里面包装的 hello1()函数	
	function<void()> func1 = hello1;
	function<void()> func2(hello1);

	
	function<void(string)> func3 = hello2;
	//func3.operator()(string str) =>
	func3("hello hello3");
	func1();

	function<int(int, int)> func4 = sum;
	cout << func4(20, 30) << endl;

	function<int(int, int)> func5 = [](int a, int b)->int {return a + b; };
	cout << func5(100, 50) << endl;

	function<void(Test*, string)> func6 = &Test::hello;
	//第一个参数传入一个临时对象
	func6(&Test(), "Hello func6");
	return 0;
}
           

function应用

#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
#include<functional>	//使用function函数对象类型
#include <ctime>
#include <string.h>
using namespace std;

/*
	bind 绑定器和函数对象
	C++ STL bind1st/bind2nd 本身还是一个函数对象

	function:绑定器,函数对象,lambda表达式 他们只能使用在一条语句中
*/

void doShowAllBooks() { cout << "查看所有书籍信息" << endl; }
void doBorrow() { cout << "借书" << endl; }
void doBack() { cout << "还书" << endl; }
int main()
{
	int choice = 0;
	map<int, function<void()>> actionMap;
	actionMap.insert({ 1,doShowAllBooks });
	actionMap.insert({ 2,doBorrow });
	actionMap.insert({ 3,doBack });

	for (;;)
	{
		cout << "__________________" << endl;
		cout << "1.查看所有书籍信息" << endl;
		cout << "2.借书" << endl;
		cout << "3.还书" << endl;
		cout << "4.查询书籍" << endl;
		cout << "5.注销" << endl;
		cout << "__________________" << endl;
		cout << "请选择" << endl;
		cin >> choice;

		//switch case 无法闭合做到开闭原则 随着选项发增加和删除就要
		auto it = actionMap.find(choice);
		if (it == actionMap.end())
		{
			cout << "输入数字无效" << endl;
		}
		else
		{
			it->second();
		}

	}


}