函数对象(函数符)

函数对象

class Linear {

private:
	double slope;
	double y0;

public:
	Linear(double s1_ = 1, double y_ = 0)
		: slope(s1_), y0(y_) {}

	double operator() (double x) {
		return (y0 + slope * x);
	}//重载()

};

Linear f1;
Linear f2(2.5, 10.0);
double y1 = f1(12.5);//传入新值,结合构造函数值 。相当于f1.operator()(12.5)
double y2 = f2(0.4);



//===============================================================
//FileName:
//          functor.cpp
//Date:
//          2019/11/29
//Author:
//          khoing(https://blog.csdn.net/qq_45391763)
//===============================================================

#include <iostream>
#include <list>
#include <iterator>
#include <algorithm>

template<class T>  // functor class defines operator()()
class TooBig
{
private:
	T cutoff;
public:
	TooBig(const T& t) : cutoff(t) {}
	bool operator()(const T& v) { return v > cutoff; }
};

//------------------------------------------------------------------------
void outint(int n) { std::cout << n << " "; }

//------------------------------------------------------------------------

int main() {
	using namespace std;
	TooBig<int> f100(100); // limit = 100

//------------------------------------------------------------------------
	int vals[10] = { 50, 100, 90, 180, 60, 210, 415, 88, 188, 201 };

//------------------------------------------------------------------------

	list<int> yadayada(vals, vals + 10); // range constructor
	list<int> etcetera(vals, vals + 10);

	//	C++11 can use the following instead
	//  list<int> yadayada = {50, 100, 90, 180, 60, 210, 415, 88, 188, 201};
	//  list<int> etcetera {50, 100, 90, 180, 60, 210, 415, 88, 188, 201};

//------------------------------------------------------------------------
	cout << "Original lists:\n";
	for_each(yadayada.begin(), yadayada.end(), outint);
	cout << endl;

//------------------------------------------------------------------------
	for_each(etcetera.begin(), etcetera.end(), outint);
	cout << endl;

//------------------------------------------------------------------------
	yadayada.remove_if(f100);// use a named function object

//------------------------------------------------------------------------
	//现在要删除另一个值,要求list中取所有大于200的值
	//设计一个类,则可以使用类成员而不是函数参数来传递额外的信息 
	etcetera.remove_if(TooBig<int>(200));   // construct a function object
	//如果已经有了一个接受两个参数的模板函数,而使用类可以将它转换为单个参数的函数对象,

//------------------------------------------------------------------------

	cout << "Trimmed lists:\n";
	for_each(yadayada.begin(), yadayada.end(), outint);
	cout << endl;
	for_each(etcetera.begin(), etcetera.end(), outint);
	cout << endl;
	// std::cin.get();
	return 0;

}

预定义的函数对象(函数符)

transform

(1)
  • 接受4个参数,前两个是指定容器区间的迭代器,第三个是指定将结果复制到哪里的迭代器,最后一个是一个函数符,被用于区间中的每个元素,生成结果中的新元素。
transform (gr.begin(),gr.end(),out,sqrt)
  • 计算每个元素的平法根,并将结果发送到输出流。
  • 可以将out 替换为 gr.begin()
    • 新值将覆盖原来的值。
  • 使用的函数符必须是接受单个参数的函数符。
(2)
  • 使用接受两个对象的函数符。
transform (gr.begin(),gr.end(),m.begin(),out,mean)
  • gr和m值的平均值。
  • 定义好的函数符。
    • plus < T > () 参数相加
    • minus < T > () 参数相减
    • multiplies < T > () 参数相乘
    • divides< T > () 参数相除
    • modulus< T > () 取余
transform(gr.begin(),gr.end(),m.begin(),out,plus<double>())

自适应函数符和函数适配器

transform(gr.begin(),gr.end(),out,sqrt)
  • 假如要将矢量gr的每个元素都增加2.5倍
  • multiples()函数符可以执行乘法运行。
  • 因此需要一个函数适配器,将接受两个参数的函数符转为接受1个参数的函数符,前面的类可以转换。
  • 但现在STL使用binder1st 和binder2nd类自动完成这一过程

//===============================================================
//FileName:
//          fundadap.cpp
//Date:
//          2019/11/29
//Author:
//          khoing(https://blog.csdn.net/qq_45391763)
//===============================================================

//using function adapters
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional> //使用bind1st
#include <iterator>

//------------------------------------------------------------------------

void Show(double);
const int LIM = 6;

//------------------------------------------------------------------------


int main()
{
	using namespace std;
	double arr1[LIM] = { 28, 29, 30, 35, 38, 59 };
	double arr2[LIM] = { 63, 65, 69, 75, 80, 99 };

//------------------------------------------------------------------------

	vector<double> gr8(arr1, arr1 + LIM);
	vector<double> m8(arr2, arr2 + LIM);

//------------------------------------------------------------------------

	cout.setf(ios_base::fixed); //固定的浮点显示
	cout.precision(1); //设显示小数精度为n位
		/*
		dec 置基数为10 相当于"%d"
		hex 置基数为16 相当于"%X"
		oct 置基数为8 相当于"%o"

		setfill(c) 设填充字符为c
		setprecision(n) 设显示小数精度为n位
		setw(n) 设域宽为n个字符

		setioflags(ios::fixed) 固定的浮点显示
		setioflags(ios::scientific) 指数表示
		setiosflags(ios::left) 左对齐
		setiosflags(ios::right) 右对齐
		setiosflags(ios::skipws 忽略前导空白
		setiosflags(ios::uppercase) 16进制数大写输出
		setiosflags(ios::lowercase) 16进制小写输出
		setiosflags(ios::showpoint) 强制显示小数点
		setiosflags(ios::showpos) 强制显示符号
		*/
			
//------------------------------------------------------------------------

	cout << "gr8:\t";
	for_each(gr8.begin(), gr8.end(), Show);
	cout << endl;

//------------------------------------------------------------------------

	cout << "m8: \t";
	for_each(m8.begin(), m8.end(), Show);
	cout << endl;

//------------------------------------------------------------------------

	vector<double> sum(LIM);
	transform(gr8.begin(), gr8.end(), m8.begin(), sum.begin(),plus<double>());

//------------------------------------------------------------------------

	cout << "sum:\t";
	for_each(sum.begin(), sum.end(), Show);
	cout << endl;

//------------------------------------------------------------------------

	vector<double> prod(LIM);
	transform(gr8.begin(), gr8.end(), prod.begin(),bind1st(multiplies<double>(), 2.5));
	//bind1st	2.5 op value
	//bind2nd   value op 2.5

//------------------------------------------------------------------------

	cout << "prod:\t";
	for_each(prod.begin(), prod.end(), Show);
	cout << endl;


	return 0;
}

void Show(double v)
{
	std::cout.width(6);
	std::cout << v << ' ';
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值