C++函数符以及Java类似功能

2 篇文章 0 订阅

C++的函数符概念

函数符也称为函数对象,或伪函数,是将函数或者类对象当作实参使用

其中,将类实例对象当作函数对象使用的,称为类函数符

类函数符是通过重载"()"操作符实现的

两者使用方法:

#include <list>

bool tooBig(int n) { return n > 100; }

class toobig {
public:
	bool operator()(int n) { return n > 100; }
};

int main() {
	std::list<int> mylist;
	mylist.remove_if(tooBig);
	toobig tb;
	mylist.remove_if(tb);
}

效果完全一致,类操作符的好处是,可以通过私有变量实现算法定制,例如toobig类,增加一个base对象,重载函数修改为"return n>base;",就能够自定义toobig的基准。

 

C++ STL提供了函数符概念,主要有三种(五种)类型:

  • 生成器:无需参数就可以调用
  • 一元函数:需要一个参数。如果返回值为bool类型,则称为谓词
  • 二元函数:需要两个参数。如果返回值为bool类型,则称为二元谓词

主要应用在非成员算法函数和某些STL类的部分成员函数中,例如list类的remove_if方法,可以接收函数符来决定删除哪些对象

又比如sort方法,其第三个参数就是函数符,用来指定排序条件

C++预置了一些函数符,存放在functional头文件中:

运算符函数符
+plus
-minus
*multiplies
/divides
%modulus
-negate
==equal_to
!=not_eqaul_to
>greater
<less
>=greater_equal
<=less_eqaul
&&logical_and
||logical_or
!logical_not

基本覆盖了常用数学和逻辑运算,代码类似:

template<class _Ty = void>
	struct divides
	{	// functor for operator/
	_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty first_argument_type;
	_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty second_argument_type;
	_CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty result_type;

	constexpr _Ty operator()(const _Ty& _Left, const _Ty& _Right) const
		{	// apply operator/ to operands
		return (_Left / _Right);
		}
	};

此外还提供了两个参数绑定类及同功能的绑定方法:binder1st类、binder2nd类、bind1st方法、bind2nd方法,用来实现一元函数和二元函数之间的转换,例如divides函数符,需要接收两个参数,如果想固定除数(_Left)为100,就可以使用(以int为例):

bind2nd(100.divides<int>()) 来代替divides,例如:

transform(mylist.begin(),mylist.end(),iter,bind2nd(100,divides<double>()));

之所以使用函数符而不是函数指针,原因是函数指针需要指定返回类型,而STL是模板类,使用了泛型,如果要用函数指针,就必须为每种类型都适配一个实现,非常麻烦。

实际上STL在应用函数符的时候,底层也是靠迭代器进行的,也就是类型无关,例如remove_if方法:

template<class _Pr1>
		void remove_if(_Pr1 _Pred)
		{	// erase each element satisfying _Pred
		_Remove_if(_Pred);
		}

	template<class _Pr1>
		void _Remove_if(_Pr1& _Pred)
		{	// erase each element satisfying _Pred
		for (iterator _First = begin(); _First != end(); )
			if (_Pred(*_First))
				_First = erase(_First);
			else
				++_First;
		}

Java的类似实现

Java 8也提供了将函数实例对象当作参数,调用指定方法执行操作的功能,相关接口:

Predicate<T>、Consumer<T>、Function<T>、Supplier<T>、Operator<T>

全部在java.util.function包中,包里还包含了很多(没有任何意义的)各种类型的继承接口,比如IntPredicate

Collection派生类和Map派生类都提供了如foreach、removeIf等方法使用函数符,例如:

import java.util.ArrayList;

public class Solution {
    public static void main(String args[]) {
        ArrayList<Integer> mylist=new ArrayList<>();
        mylist.removeIf(integer -> integer>100);
    }
}

和C++部分第一段示例代码功能一样

但是Java内部使用的是for循环实现而非迭代器

另外Java由于没有操作符重载,也没有面向过程式编程风格,只能将函数符划分为五个接口实现,如果不是lambda形式的话,使用起来还是比较麻烦的,这一点不如C++,个人觉得完全可以使用Method类,通过反射实现

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值