0
点赞
收藏
分享

微信扫一扫

STL_仿函数(函数对象)functors

英乐 2022-02-10 阅读 82
c++stl

仿函数(函数对象)

仿函数是C++ 早期的称呼,C++ 标准规格定案采用的是函数对象
函数对象:一种具有函数特征的对象,从行为上看,中文使用仿函数更加突出
从调用角度看,可以像函数一样被调用
从被调用者角度看,用对象所定义的function call operator(函数调用运算符operator() ) 扮演函数的实质角色
操作功能:要将某种操作当做算法的参数,唯一的方法就是先将该操作(可能拥有数条以上的指令)设计为一个函数
设计计为一个函数使用的两种方式:

  1. 设计为一个函数,再将一个函数指针当做算法的一个参数
  2. 将该操作设计为一个所谓的仿函数(在语言层面上看是一个类class),在以该仿函数产生一个对象并以此对象作为方法的一个参数

实现上看:仿函数实际上就是一个行为类似函数的对象,实现该功能,类别定义中必须自定义(或说改写,重载)function call 运算子(operator() ),使用上可以通过对象后面加上一对小括号,以此调用仿函数所定义的operator()

仿函数的分类

  1. 按照操作数operand 得个数划分,可以分为一元仿函数和二元仿函数
  2. 按照功能划分,可以分为 算数运算 arithmetic 、关系运算 rational 、逻辑运算 logical 三大类
    使用仿函数需要声明 头文件

仿函数可配接的关键

仿函数是STL 六大组件中体积最小,观念最简单,实现最容易的,在STL 中扮演一种策略角色(算法因为不同仿函数的介入而有不同的变异行为,算法的本质是不变的)

STL 仿函数应该有能力被函数配接器显示,彼此像积木一样的串接
要拥有配接能力,每一个仿函数必须定义自己的相应型别,根迭代器类似定义自己的5个相应型别
型别是为了让配接器能够取出,获得仿函数的某些信息,相应型别都只是一些typedef ,所有必要操作在编译期就全部完成了,对程序的执行效率没有任何影响,不带来任何额外负担

反函数得相应型别主要用来表现函数参数型别和传回值型别,STL 中只支持一元仿函数和二元仿函数(STL 不支持三元仿函数)分别定义型别类,类中没有data member 或 member function 唯有一些型别定义:仿函数只要依照需求选择继承其中一个class 变拥有类相应型别的能力

unary_function 一元仿函数相应型别

template <class Arg,class Result>
struct unary_function{
	typedef Arg argument_type; // 参数类型
	typedef Result result_type; // 返回值类型
};

binary_function 二元仿函数相应型别

template <class Arg1,class Arg2,class Result>
struct binary_function{
	typedef Arg1 first_argument_type;
	typedef Arg2 second_argument_type;
	typedef Result result_type;
};

按功能划分多种仿函数

算数类仿函数

STL 内建的算数类仿函数,支持加法,减法,乘法,模数(余数,modulus)否定

//加法
plus<T>
//减法
minus<T>
//乘法
multiplies<T>
//除法
divides<T>
//模取
modulus<T>
//否定
negate<T>

例:

template <class>
struct negate : public unary_function<T,T>{
	T operator()(const T& x) const {
		return -x;
	}
}

关系运算类仿函数

STL 内建的关系运算符函数支持了等于、不等于、大于、大于等于、小于,小于等于,每一个都是二元运算符

//等于
equal_to<T>
//不等于
not_equal_to<T>
//大于
greater<T>
//大于等于
greater_equal<T>
//小于
less<T>
//小于等于
less_equal<T>

逻辑运算仿函数

STL 内建支持逻辑运算类仿函数,支持了逻辑运算中的AndOrNot三种运算

logical_and<T>
logical_or<T>
logical_not<T>

证同identity 、选择select、投射 project

某些访函数对传回的参数有刻意的选择或者刻意的忽略。使用这三个。不再设计时使用。而是在画出来一层。保证间接性,间接性是抽象化的重要工具。

idedtity 证同

任何数值通过此函数不会改变。
STL 使用在 RB-tree set 因为键值就是实值

struct identity:public unary_function<T,T>{
	const T& operator()(const T&x) const {
		return x;			
	}	
};
select 选择

在一个元素中。选择组成部分,如pair 的两个元素的选择
STL 中RB-tree 中使用 map 的pair 第一个元素就是键值

template <class Pair>
struct select1st : public unary_funiction<Pair,typename Pair::first_type>{
	const typename Pair::first_type& operator()(const Pair &x)const {
		return x.first;
	}
};
投射函数 project

将两个参数中的一个参数投射而出。

template <class Arg1,class Arg2>
struct project1st : public binary_function<Arg1,Arg2,Arg1>{
	Arg1 operator()(const Arg1&x ,Arg2&) const{
		return x;
	}
}
举报

相关推荐

0 条评论