栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++bind和function

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++bind和function

C++ STL中的绑定器

bind1st : operator()的第一个形参变量绑定成一个确定的值
bind2nd : operator()的第二个形参变量绑定成一个确定的值
绑定器 + 二元函数对象 =》 一元函数对象

把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(), 70));
//auto it1 = my_find_if(vec.begin(), vec.end(),
//bind2nd(less(), 70));
if (it1 != vec.end())
{
	vec.insert(it1, 70);
}
showContainer(vec);

my_find_if

遍历俩个迭代器区间,如果满足comp运算,返回当前迭代器,如果都不满足,返回end

template
Iterator my_find_if(Iterator first, Iterator last, Compare comp)
{
	for (; first != last; ++first)
	{
		if (comp(*first)) // comp.operator()(*first)
		{
			return first;
		}
	}
	return last;
}
_mybind1st实现
template
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;
};

template
_mybind1st mybind1st(Compare comp, const T &val)
{
	// 直接使用函数模板,好处是,可以进行类型的推演
	return _mybind1st(comp, val);
}

function

留下函数对象,lambda表达式的类型留下来

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

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

function func1 = hello1;
func1(); // func1.operator()() => hello1()

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

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

function func5 = &Test::hello;
func5(&Test(), "call Test::hello!");
使用function的好处

下面这块代码会随着我们需要的更改然后改来改去,不好维护,无法做到“开闭原则”

int choice = 0;
	//       C的函数指针
	map> 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();
		}
		// 不好,因为这块代码无法闭合  无法做到“开-闭原则
		
	}

而我们使用function之后

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


map> 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 });

auto it = actionMap.find(choice); // map  pair  first second
if (it == actionMap.end())
{
	cout << "输入数字无效,重新选择!" << endl;
}
else
{
	it->second();
}
function的底层原理 模板的完全特例化和非完全(部分)特例化
emplate
class Vector 
{
public:
	Vector() { cout << "call Vector template init" << endl; }
};
// 下面这个是对char*类型提供的完全特例化版本  #1
template<>
class Vector
{
public:
	Vector() { cout << "call Vector init" << endl; }
};
// 下面这个是对指针类型提供的部分特例化版本  #2
template
class Vector
{
public:
	Vector() { cout << "call Vector init" << endl; }
};

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

// 针对函数(有一个返回值,有两个形参变量)类型提供的部分特例化
template
class Vector
{
public:
	Vector() { cout << "call Vector init" << endl; }
};
Vector vec1;
Vector vec2;
Vector vec3;
Vector vec4;
Vector vec5; // function
模板实参推演
template
bool compare(T a, T b)
{
	cout << "template compare" << endl;
	return a > b;
}
template<>
bool compare(const char*a, const char*b)
{
	cout << "compare" << endl;
	return strcmp(a, b) > 0;
}
int main()
{
	compare(10, 20); // 
	compare("aaa", "bbb"); // T const char*
	return 0;
}
function函数对象类型的实现原理
template
class myfunction
{
public:
	using PFUNC = R(*)(A1);
	myfunction(PFUNC pfunc) :_pfunc(pfunc) {}
	R operator()(A1 arg)
	{
		return _pfunc(arg); // hello(arg)
	}
private:
	PFUNC _pfunc;
};
template
class myfunction
{
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的强大机制,用…表示多个传入的参数。
避免了因为参数的个数不同重写多个myfunction

template
class myfunction
{
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 func1(hello);
	func1("hello world!"); // func1.operator()("hello world!")

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

	return 0;
}
bind

bind绑定器 =》 返回的结果还是一个函数对象
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 func1 = bind(hello, _1);
	func1("hello china!");
	func1("hello shan xi!");
	func1("hello si chuan!");

	return 0;
}
lambda

C++11 函数对象的升级版 =》 lambda表达式
函数对象的缺点:
使用在泛型算法参数传递 比较性质/自定义操作 优先级队列 智能指针

lambda表达式的语法:
捕获外部变量->返回值{操作代码};

如果lambda表达式的返回值不需要,那么"->返回值"可以省略的

[捕获外部变量]
[]:表示不捕获任何外部变量
[=]:以传值的方式捕获外部的所有变量
[&]:以传引用的方式捕获外部的所有变量
[this]:捕获外部的this指针
[=,&a]:以传值的方式捕获外部的所有变量,但是a变量以传引用的方式捕获
[a, b]:以值传递的方式捕获外部变量a和b
[a, &b]:a以值传递捕获,b以传引用的方式捕获

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/875734.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号