502-C++的绑定器(讲解大全)

本文详细介绍了C++中的函数对象,包括STL中的绑定器bind1st和bind2nd,以及C++11引入的bind绑定器和function函数对象。通过示例展示了如何使用这些工具实现一元和二元函数对象,以及如何利用它们进行函数参数的预设定。此外,文章还提及了lambda表达式的底层机制,并讨论了C++11的function在实际应用中的示例,如用于管理各种操作的映射表。
摘要由CSDN通过智能技术生成

绑定器和函数对象operator()

1.C++ STL中的绑定器
bind1st : operator()的第一个形参变量绑定成一个确定的值
bind2nd : operator()的第二个形参变量绑定成一个确定的值

2.C++11从Boost库中引入了bind绑定器和function函数对象机制

3.lambda表达式 底层依赖函数对象的机制实现的

我们先准备好环境

在这里插入图片描述

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

template<typename Container>
void showContainer(Container& con)
{
	typename Container::iterator it = con.begin();
	//编译器是从上到下编译的,这个还没有实例化,它不知道这个名字作用域后面的iterator是类型还是变量
	//typename告知编译器后面类型的作用域后面是类型
	for (; it != con.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);//随机出来的数字,并不是有序的 
	}

	showContainer(vec);
	sort(vec.begin(), vec.end());//默认小到大排序,传入的是起始和末尾的后继的迭代器
	showContainer(vec);
	//greater 二元函数对象
	sort(vec.begin(), vec.end(), greater<int>());//大到小排序
	showContainer(vec);
	return 0;
}

在这里插入图片描述

C++ STL的绑定器

在这里插入图片描述

把70按顺序插入到vec容器当中,找第一个小于70的数字

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

template<typename Container>
void showContainer(Container& con)
{
	typename Container::iterator it = con.begin();
	for (; it != con.end(); ++it)
	{
		cout << *it << " ";
	}
	cout << endl;
}

template<typename Iterator, typename Compare>
Iterator my_find_if(Iterator first, Iterator last, Compare comp)
//遍历这2个迭代器之间的元素,如果满足函数对象的运算,就返回当前迭代器,如果都不满足,返回end()
{
	for (; first != last; ++first)
	{
		if (comp(*first))//comp.operator()(*first)一元函数对象,因为要从容器拿1个元素和它指定的元素比较
		//my_find_if需要1元函数对象,而在库里面都是二元的
		{
			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);//greater
	}
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, val);
}

int main()
{
	vector<int> vec;
	srand(time(nullptr));
	for (int i = 0; i < 20; ++i)
	{
		vec.push_back(rand() % 100 + 1);
	}

	showContainer(vec);
	sort(vec.begin(), vec.end());//默认小到大排序
	showContainer(vec);

	//greater 二元函数对象
	sort(vec.begin(), vec.end(), greater<int>());//大到小排序
	showContainer(vec);

	/*
	把70按顺序插入到vec容器当中   找第一个小于70的数字
	operator()(const T &val)
	greater   a > b
	less      a < b
	绑定器 + 二元函数对象 =》 一元函数对象
	bind1st: + greater bool operator()(70, const _Ty& _Right)
	bind2nd: + less bool operator()(const _Ty& _Left, 70)
	*/

	auto it1 = my_find_if(vec.begin(), vec.end(),
		mybind1st(greater<int>(), 70));
	//auto it1 = my_find_if(vec.begin(), vec.end(),bind2nd(less<int>(), 70));
	if (it1 != vec.end())
	{
		vec.insert(it1, 70);
	}
	showContainer(vec);

	return 0;
}

在这里插入图片描述

C++ 11的绑定器(function使用示例)

在这里插入图片描述

void hello1()
{
	cout << "hello world!" << endl;
}
void hello2(string str)//void (*pfunc)(string)
{
	cout << str << endl;
}
int sum(int a, int b)
{
	return a + b;
}

class Test
{
public://必须依赖一个对象void (Test::*pfunc)(string)
	void hello(string str) { cout << str << endl; }
};

int main()
{
	/*
	1.用函数类型实例化function
	2.通过function调用operator()函数的时候,需要根据函数类型传入相应的参数
	*/

	//从function的类模板定义处,看到希望用一个函数类型实例化function
	function<void()> func1 = hello1;
	func1();//func1.operator()() => hello1()

	function<void(string)> func2 = hello2;
	func2("hello hello2!");//func2.operator()(string str) => hello2(str)

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

	//operator()
	function<int(int, int)> func4 = [](int a, int b)->int {return a + b; };
	cout << func4(100, 200) << endl;

	function<void(Test*, string)> func5 = &Test::hello;
	func5(&Test(), "call Test::hello!");

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


void doShowAllBooks() { cout << "查看所有书籍信息" << endl; }
void doBorrow() { cout << "借书" << endl; }
void doBack() { cout << "还书" << endl; }
void doQueryBooks() { cout << "查询书籍" << endl; }
void doLoginOut() { cout << "注销" << endl; }

int main()
{
	int choice = 0;
	//      C的函数指针
	map<int, function<void()>> actionMap;
	actionMap.insert({ 1, doShowAllBooks });//老版本:insert(make_pair(xx,xx));
	actionMap.insert({ 2, doBorrow });
	actionMap.insert({ 3, doBack });
	actionMap.insert({ 4, doQueryBooks });
	actionMap.insert({ 5, doLoginOut });

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

		auto it = actionMap.find(choice);//map  pair  first second
		if (it == actionMap.end())
		{
			cout << "输入数字无效,重新选择!" << endl;
		}
		else
		{
			it->second();
		}
		//不好,因为这块代码无法闭合  无法做到“开-闭原则”
		/*switch (choice)
		{
		case 1:
			break;
		case 2:
			break;
		case 3:
			break;
		case 4:
			break;
		case 5:
			break;
		default:
			break;
		}*/
	}

	return 0;
}

在这里插入图片描述

模板的完全特例化和部分特例化

模板的完全特例化和非完全(部分)特例化
模板的实参推演 => 基本概念很简单

有完全特例化,就选择对应的完全特例化,有部分特例化,就匹配部分特例化,没有的话,就原模板实例化

示例1

template<typename T>
bool compare(T a, T b)
{
	cout << "template compare" << endl;
	return a > b;
}
template<>
bool compare<const char*>(const char*a, const char*b)//特例化 
{
	cout << "compare<const char*>" << endl;
	return strcmp(a, b) > 0;
}
int main()
{
	compare(10, 20);// 
	compare("aaa", "bbb");//T const char*
	return 0;
}

第二个是特例化了。
在这里插入图片描述
示例2

template<typename T>
class Vector 
{
public:
	Vector() { cout << "call Vector template init" << endl; }
};
//下面这个是对char*类型提供的完全特例化版本  #1
template<>//特例化的语法
class Vector<char*>
{
public:
	Vector() { cout << "call Vector<char*> init" << endl; }
};
//下面这个是对指针类型提供的部分特例化版本  #2
template<typename Ty>
class Vector<Ty*>
{
public:
	Vector() { cout << "call Vector<Ty*> init" << endl; }
};

//指针函数指针(有返回值,有两个形参变量)提供的部分特例化
template<typename R, typename A1, typename A2>
class Vector<R(*)(A1, A2)>
{
public:
	Vector() { cout << "call Vector<R(*)(A1, A2)> init" << endl; }
};

//针对函数(有一个返回值,有两个形参变量)类型提供的部分特例化
template<typename R, typename A1, typename A2>
class Vector<R(A1, A2)>
{
public:
	Vector() { cout << "call Vector<R(A1, A2)> init" << endl; }
};

int sum(int a, int b) { return a + b; }
int main()
{
	Vector<int> vec1;
	Vector<char*> vec2;
	Vector<int*> vec3;
	Vector<int(*)(int, int)> vec4;
	Vector<int(int, int)> vec5;//function

	//注意区分一下函数类型和函数指针类型
	typedef int(*PFUNC1)(int, int);
	PFUNC1 pfunc1 = sum;
	cout << pfunc1(10, 20) << endl;

	typedef int PFUNC2(int, int);
	PFUNC2 *pfunc2 = sum;
	cout << (*pfunc2)(10, 20) << endl;

	return 0;
}

在这里插入图片描述

模板的实参推演

#include <iostream>
#include <typeinfo>
using namespace std;


int sum(int a, int b) { return a + b; }
//T包含了所有的大的类型  返回值,所有形参的类型都取出来
template<typename T>
void func(T a)
{
	cout << typeid(T).name() << endl;
}

template<typename R, typename A1, typename A2>
void func2(R(*a)(A1, A2))
{
	cout << typeid(R).name() << endl;
	cout << typeid(A1).name() << endl;
	cout << typeid(A2).name() << endl;
}

class Test
{
public:
	int sum(int a, int b) { return a + b; }
};

template<typename R, typename T, typename A1, typename A2>
void func3(R(T::* a)(A1, A2))
{
	cout << typeid(R).name() << endl;
	cout << typeid(T).name() << endl;
	cout << typeid(A1).name() << endl;
	cout << typeid(A2).name() << endl;
}
int main()
{
	func(10);
	func("aaa");
	func(sum);//T  int (*)(int,int)   int (int,int)
	func2(sum);
	func3(&Test::sum);//int (__thiscall Test::*)(int,int)

	return 0;
}

在这里插入图片描述

function的实现原理

#include <iostream>
#include <typeinfo>
#include <string>
#include <functional>
using namespace std;

/*
function函数对象类型的实现原理
*/
void hello(string str) { cout << str << endl; }
int sum(int a, int b) { return a + b; }
///
template<typename Fty>
class myfunction {};

 
template<typename R, typename A1>
class myfunction<R(A1)>
{
public:
	using PFUNC = R(*)(A1);
	myfunction(PFUNC pfunc) :_pfunc(pfunc) {}
	R operator()(A1 arg)
	{
		return _pfunc(arg);//hello(arg)
	}
private:
	PFUNC _pfunc;
};

///
template<typename R, typename A1, typename A2>
class myfunction<R(A1, A2)>
{
public:
	using PFUNC = R(*)(A1, A2);
	myfunction(PFUNC pfunc) :_pfunc(pfunc) {}
	R operator()(A1 arg1, A2 arg2)
	{
		return _pfunc(arg1, arg2);//hello(arg)
	}
private:
	PFUNC _pfunc;
};
//

template<typename R, typename... A>//一组可变参数个数
class myfunction<R(A...)>
{
public:
	using PFUNC = R(*)(A...);
	myfunction(PFUNC pfunc) :_pfunc(pfunc) {}
	R operator()(A... arg)
	{
		return _pfunc(arg...);//hello(arg) 表示一组形参变量
	}
private:
	PFUNC _pfunc;
};

int main()
{
	function<void(string)> func1(hello);
	func1("hello world!");//func1.operator()("hello world!")

	myfunction<int(int, int)> func2(sum);
	cout << func2(10, 20) << endl;

	return 0;
}

C++11 绑定器介绍

C++11 bind绑定器 => 返回的结果还是一个函数对象
bind占位符最多有20个参数。

#include <iostream>
#include <typeinfo>
#include <string>
#include <memory>
#include <vector>
#include <functional>
#include <thread>
using namespace std;
using namespace placeholders;

/*
C++11 bind绑定器 => 返回的结果还是一个函数对象
*/

void hello(string str) { cout << str << endl; }
int sum(int a, int b) { return a + b; }
class Test
{
public:
	int sum(int a, int b) { return a + b; }
};
int main()
{
	//bind是函数模板 可以自动推演模板类型参数
	bind(hello, "hello bind!")();//返回的结果是绑定器,也就是函数对象 
	cout << bind(sum, 10, 20)() << endl;
	cout << bind(&Test::sum, Test(), 20, 30)() << endl;

	//参数占位符  绑定器出了语句,无法继续使用
	//只是占位的作用,调用的时候就要传递参数了 
	//书写的时候使用多少个占位符,就是意味着用户调用的时候要传入几个参数
	bind(hello, _1)("hello bind 2!");
	cout << bind(sum, _1, _2)(200, 300) << endl;

	//此处把bind返回的绑定器binder就复用起来了
	function<void(string)> func1 = bind(hello, _1);
	func1("hello china!");
	func1("hello shan xi!");
	func1("hello si chuan!");

	return 0;
}

在这里插入图片描述

在这里插入图片描述
有20个参数占位符

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林林林ZEYU

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值