适配器——STL

适配器


函数对象适配器


前提引入:

 class MyPrint
{
public:
     //原先只有val,但是想在val的基础上加上可以自定义的start
	void operator()(int val,int start)
	{
		cout << val + start << endl;
	}
};

int main()
{
	vector<int> v;
	
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}

	for_each(v.begin(), v.end(), MyPrint());//注意,仿函数放进去的是匿名对象
	//for_each的底层是从范围内开始遍历,然后依次进行解引用,每次返回一个数,然后将这个数传进后面的仿函数中。
	//但是如果仿函数中打印的数字发生了变化(从一个数变成了两个数的相加),那么原先返回的一个数就不够传参,需要再传一个参数。所以需要将另一个数创建出来,并与MyPrint()进行合并

	return 0;
} 

进行改变:

1,利用bind2nd进行绑定

2,继承:public binary_function<参数1类型,参数2类型,返回值类型> —这个是二元继承的父类

3,加const,下面重载的()的函数已经是在继承的父类中写好的,子类中进行重写的状态是只读。

class MyPrint:public binary_function<int,int,void>//进行继承
{
public:
	void operator()(int val,int start)const
	{
		cout << val + start << endl;
	}
};

int main()
{
	vector<int> v;
	
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}

	int num;
	cin >> num; 

	for_each(v.begin(), v.end(), bind2nd(MyPrint(),num));//通过bind2nd将仿函数和另一个自定义的参数绑定。
    //注意,这里的bind1st是将传进来的num参数作为第一个参数传入仿函数中,而bind2nd是作为第二参数传入。
	return 0;
}

完成了适配器的功能,将仿函数的参数从一个适配成了两个。



取反适配器


一元取反

前提引入:

如果想在存有0-9的容器中找到一个大于5的数,可以使用find_if函数从容器的开始到结尾进行遍历寻找,传入GreaterThanFive()的仿函数进行寻找,然后就会返回6。这时如果想返回一个小于5的数,那么可以直接通过修改仿函数中的>为<就可以找到。也可以通过使用适配器的功能。


进行改变:

1,使用not1进行取反

2,继承:public unary_function<int,bool> —这个是一元继承

3,加const

class GreaterThanFive :public unary_function<int,bool>
{
public:
	bool operator()(int val) const//返回值是bool类型
	{
		return val > 5;
	}
};

int main()
{
	vector<int> v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}

	vector<int>::iterator pos = find_if(v.begin(), v.end(), not1(GreaterThanFive()));//find_if的返回值类型是迭代器
    //还有一种写法:直接使用内建函数对象(这样就不用再自己写仿函数了),使用一个内建函数对象(bind2nd)加一个数字表示大于这个数字
	//vector<int>::iterator pos = find_if(v.begin(),v.end(),not1(bind2nd(greater<int>(),5)));
    

	//打印迭代器的数据
	if (pos != v.end())
	{
		cout << *pos << endl;
	}
	else
	{
		cout << "没有找到" << endl;
	}

	return 0;
}


二元取反

前提引入:

将容器中的数据通过使用less< int >()的内建函数对象 改变为从大到小的排列

进行改变:

在排序中对内建函数对象进行适配器的调整,这里并不需要继承以及加const,因为不是自己写的类,在源代码中已经是操作过了,所以只需要在less< int >()前面加个not2即可。

int main()
{
	vector<int> v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}

	sort(v.begin(), v.end(), not2(less<int>()));


	//进行容器中数据的打印
	for_each(v.begin(), v.end(), [](int val) {cout << val << endl; });
	return 0;
}


函数适配器


前提引入:

将容器中的数据遍历,现在要求在遍历的基础上加1000,像上面的函数对象适配器一样。

void myPrint3(int val)
{
	cout << val << endl;
}

int main()
{
	vector<int> v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}

	for_each(v.begin(), v.end(), myPrint3);//0123456789
	return 0;
}

进行改变:

由于使用的是回调函数,而不是内建函数对象,所以也就不用自己写类的继承和const。但是需要将myPrint3这个函数指针变成函数对象,使用ptr_fun函数。然后再将这个函数对象与自定义的数字进行合并。

void myPrint3(int val,int start)//函数的参数由一个变成两个
{
	cout << val + start<< endl;
}

int main()
{
	vector<int> v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}

	for_each(v.begin(), v.end(), bind2nd(ptr_fun(myPrint3),1000));
	return 0;
}


成员函数适配器


前提引入:

将存放Person类数据的vector容器使用回调函数进行遍历(全局函数)。然后要求不使用回调函数,使用类中的成员函数进行遍历。

class Person
{
public:
	Person(string name,int age)
	{
		this->m_age = age;
		this->m_name = name;
	}
	string m_name;
	int m_age;

};

void myPrint(Person&p)
{
	cout << p.m_name << " " << p.m_age << endl;
}

int main()
{
	vector< Person > v;

	Person p1("a", 10);
	Person p2("b", 20);
	Person p3("c", 30);
	Person p4("d", 40);

	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);

	for_each(v.begin(), v.end(), myPrint);

	return 0;
}

进行改变:

使用类中的成员函数实现遍历。首先需要获取到成员函数的地址,然后再使用mem_fun_ref将成员函数适配(可以理解为适配成全局函数了,和刚才的myPrint一样)

class Person
{
public:
	Person(string name,int age)
	{
		this->m_age = age;
		this->m_name = name;
	}
	string m_name;
	int m_age;

	void showPerson()
	{
		cout << this->m_name << " " << this->m_age << endl;
	}
};

int main()
{
	vector< Person > v;

	Person p1("a", 10);
	Person p2("b", 20);
	Person p3("c", 30);
	Person p4("d", 40);

	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);

	for_each(v.begin(), v.end(), mem_fun_ref( & Person::showPerson));
	return 0;
}

如果想让所有的这个类的对象都进行某个操作,那么就可以使用这种方法。

如果在这个基础上的所有年龄再加100

class Person
{
public:
	Person(string name,int age)
	{
		this->m_age = age;
		this->m_name = name;
	}
	string m_name;
	int m_age;

	void showPerson()
	{
		cout << this->m_name << " " << this->m_age << endl;
	}

	void ageAdd()
	{
		this->m_age += 100;
	}
};

int main()
{
	vector< Person > v;

	Person p1("a", 10);
	Person p2("b", 20);
	Person p3("c", 30);
	Person p4("d", 40);

	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);

	for_each(v.begin(), v.end(), mem_fun_ref( & Person::showPerson));
	for_each(v.begin(), v.end(), mem_fun_ref(&Person::ageAdd));//将容器中所有的Person对象的年龄加100
	for_each(v.begin(), v.end(), mem_fun_ref(&Person::showPerson));//然后再进行一次打印
	return 0;
}
  • 26
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 42
    评论
评论 42
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

是小明同学啊

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

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

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

打赏作者

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

抵扣说明:

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

余额充值