标签:
本文介绍的东西,在STL历史上有两个不同的名称。仿函数(functors)是早期的命名,C++标准定案后,采用的新名称是函数对象(function objects)。
函数对象,顾名思义,首先是对象(后面我们可以看到,函数对象是用struct而不是class定义的),其次,我们可以像调用函数一样,调用函数对象。这和函数指针很像,遗憾的是,函数指针不能满足面向对象的要求,不能满足STL对模板抽象性的要求,而且函数指针不能与STL其他组件搭配使用。于是聪明的科学家们发挥奇思妙想,给赤裸裸的函数裹上一层对象,并重载operator()方法,把函数的实现写到operator()中,这样我们就可以把函数当做对象传递,是不是很机智?
就实现而言,函数对象实际上就是一个“行为类似函数”的对象。为了能够“行为类似函数”,对象内必须重载operator()运算符,然后我们就可以在函数对象的后面加上一对小括号,以此调用函数对象定义的operator()。
函数对象和算法之间的关系如下图所示:
我用VS2013写的程序(github),函数对象的实现版本的位于cghSTL/version/ cghSTL-0.6.5.rar
本文介绍的函数对象需要以下文件:
1. cghStl_funcbase.h,包含函数对象的基类,所有函数对象必须继承自基类,位于cghSTL/function objects/
2. cgh_function_obj.h:本文的主角,包含算术类函数对象、关系运算类函数对象、逻辑运算类函数对象的实现,位于cghSTL/functionobjects/
3. test_relational_function_obj.cpp,测试关系运算类函数对象,位于cghSTL/test/
4. test_logical_function_obj.cpp,测试逻辑运算类函数对象,位于cghSTL/test/
5. test_arithmetic_function_obj.cpp,测试算术类函数对象,位于cghSTL/test/;
STL函数对象应该有能力被函数配接器(function adapter)修饰,彼此像积木一样串接起来。为了拥有配接能力,每一个函数对象必须定义自己的相应型别(associative types),就像迭代器要融入STL大家庭,也必须依照规定,定义自己的5个型别一样。这些型别是为了让配接器能够取出函数对象的信息。型别定义都只是一些typedef,所有操作在编译期完成,对程序运行期的效率没有影响。
函数对象的型别主要用来表现函数参数类型和返回值类型。在cghStl_funcbase.h(cghSTL/functionobjects/)中,我们定义了两个classes,分别代表一元函数对象和二元函数对象的基类。任何函数对象必须继承自两个基类中的一个,只要继承了基类,便拥有了型别,也就拥有了配接能力。
cghStl_funcbase.h定义了函数对象的基类(共两个),代码如下
/******************************************************************* * Copyright(c) 2016 Chen Gonghao * All rights reserved. * * chengonghao@yeah.net * * 文件内容:算术类(Arthmetic)仿函数的实现 ******************************************************************/ #ifndef _CGH_STL_FUNC_BASE_H_ #define _CGH_STL_FUNC_BASE_H_ namespace CGH{ /* unary_function 用来呈现一元函数的参数类型和返回值类型 STL 规定,每一个 adaptable unary function 都应该继承 unary_function */ template<class arg, class result> struct unary_function { typedef arg argument_type; typedef result result_type; }; /* binary_function 用来呈现二元函数的第一个参数类型、第二个参数类型、返回值类型 STL 规定,每一个 adaptable binary function 都应该继承 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; }; } #endif
cgh_function_obj.h中包含了三类函数对象:算术类、关系运算类、逻辑运算类。
函数对象的设计比较简单,有疑问的地方已给出注释,代码如下
/******************************************************************* * Copyright(c) 2016 Chen Gonghao * All rights reserved. * * chengonghao@yeah.net * * 文件内容:函数对象的实现 ******************************************************************/ #ifndef _CGH_FUNCTION_OBJ_H_ #define _CGH_FUNCTION_OBJ_H_ #include "cghStl_funcbase.h" namespace CGH{ #pragma region 算术类(Arithmetic)函数对象 /* 相加 */ template<class T> struct plus : public binary_function<T, T, T> { T operator()(const T& x, const T& y) const { return x + y; } }; /* 相减 */ template<class T> struct minus : public binary_function<T, T, T> { T operator()(const T& x, const T& y) const { return x - y; } }; /* 相乘 */ template<class T> struct multiplies : public binary_function<T, T, T> { T operator()(const T& x, const T& y) const { return x * y; } }; /* 相除 */ template<class T> struct divides : public binary_function<T, T, T> { T operator()(const T& x, const T& y) const { return x / y; } }; /* 求余 */ template<class T> struct modulus : public binary_function<T, T, T> { T operator()(const T& x, const T& y) const { return x % y; } }; /* 取反 */ template<class T> struct negate : public unary_function<T, T> { T operator()(const T& x) const { return -x; } }; #pragma endregion #pragma region 关系运算类(Relational)函数对象 /* 等于 */ template<class T> struct equal_to : public binary_function<T, T, bool> { bool operator()(const T& x, const T& y) const { return x == y; } }; /* 不等于 */ template<class T> struct not_equal_to : public binary_function<T, T, bool> { bool operator()(const T& x, const T& y) const { return x != y; } }; /* 大于 */ template<class T> struct greater : public binary_function<T, T, bool> { bool operator()(const T& x, const T& y) const { return x > y; } }; /* 小于 */ template<class T> struct less : public binary_function<T, T, bool> { bool operator()(const T& x, const T& y) const { return x < y; } }; /* 大于等于 */ template<class T> struct greater_equal : public binary_function<T, T, bool> { bool operator()(const T& x, const T& y) const { return x >= y; } }; /* 小于等于 */ template<class T> struct less_equal : public binary_function<T, T, bool> { bool operator()(const T& x, const T& y) const { return x <= y; } }; #pragma endregion #pragma region 逻辑运算类(logical)函数对象 /* 逻辑与 */ template<class T> struct logical_and : public binary_function<T, T, bool> { bool operator()(const T& x, const T& y) const { return x && y; } }; /* 逻辑或 */ template<class T> struct logical_or : public binary_function<T, T, bool> { bool operator()(const T& x, const T& y) const { return x || y; } }; /* 逻辑非 */ template<class T> struct logical_not : public unary_function<T, bool> { bool operator()(const T& x) const { return !x; } }; #pragma endregion } #endif
测试环节的主要内容已在注释中说明
/******************************************************************* * Copyright(c) 2016 Chen Gonghao * All rights reserved. * * chengonghao@yeah.net * * 文件内容:测试算术类(Arthmetic)函数对象(仿函数) ******************************************************************/ #include "stdafx.h" #include <iostream> #include "cgh_function_obj.h" int _tmain(int argc, _TCHAR* argv[]) { using namespace::CGH; plus<int> plusObj; minus<int> minusObj; multiplies<int> multipliesObj; divides<int> dividesObj; modulus<int> modulusObj; negate<int> nagateObj; std::cout << std::endl; std::cout << "算术类函数对象共5个:plus、minus、multiplies、divides、modulus、negate" << std::endl << std::endl; std::cout << "************************ 测试算术类函数对象1 ***************************" << std::endl << std::endl; std::cout << "plusObj(3, 5) = " << plusObj(3, 5) << std::endl << std::endl; std::cout << "minusObj(3, 5) = " << minusObj(3, 5) << std::endl << std::endl; std::cout << "multipliesObj(3, 5) = " << multipliesObj(3, 5) << std::endl << std::endl; std::cout << "dividesObj(3, 5) = " << dividesObj(3, 5) << std::endl << std::endl; std::cout << "modulusObj(3, 5) = " << modulusObj(3, 5) << std::endl << std::endl; std::cout << "nagateObj(3) = " << nagateObj(3) << std::endl << std::endl; std::cout << "************************* 测试算术类函数对象2 **************************" << std::endl << std::endl; std::cout << "plus<int>()(3, 5) = " << plus<int>()(3, 5) << std::endl << std::endl; std::cout << "minus<int>()(3, 5) = " << minus<int>()(3, 5) << std::endl << std::endl; std::cout << "multiplies<int>()(3, 5) = " << multiplies<int>()(3, 5) << std::endl << std::endl; std::cout << "divides<int>()(3, 5) = " << divides<int>()(3, 5) << std::endl << std::endl; std::cout << "modulus<int>()(3, 5) = " << modulus<int>()(3, 5) << std::endl << std::endl; std::cout << "negate<int>()(3) = " << negate<int>()(3) << std::endl << std::endl; system("pause"); return 0; }
测试环节的主要内容已在注释中说明
test_relational_function_obj.cpp
/******************************************************************* * Copyright(c) 2016 Chen Gonghao * All rights reserved. * * chengonghao@yeah.net * * 文件内容:测试关系运算类(Relational)函数对象(仿函数) ******************************************************************/ #include "stdafx.h" #include <iostream> #include "cgh_function_obj.h" int _tmain(int argc, _TCHAR* argv[]) { using namespace::CGH; equal_to<int> equal_to_obj; not_equal_to<int>not_equal_to_obj; greater<int> greater_obj; greater_equal<int> greater_equal_obj; less<int> less_obj; less_equal<int> less_equal_obj; std::cout << std::endl; std::cout << "关系类函数对象共5个:equal_to、not_equal_to、greater 、\n\t\t\tgreater_equal、less、less_equal" << std::endl << std::endl; std::cout << "************************ 测试关系类函数对象1 ***************************" << std::endl << std::endl; std::cout << "equal_to_obj(3, 5) = " << equal_to_obj(3, 5) << std::endl << std::endl; std::cout << "not_equal_to_obj(3, 5) = " << not_equal_to_obj(3, 5) << std::endl << std::endl; std::cout << "greater_obj(3, 5) = " << greater_obj(3, 5) << std::endl << std::endl; std::cout << "greater_equal_obj(3, 5) = " << greater_equal_obj(3, 5) << std::endl << std::endl; std::cout << "less_obj(3, 5) = " << less_obj(3, 5) << std::endl << std::endl; std::cout << "less_equal_obj(3, 5) = " << less_equal_obj(3, 5) << std::endl << std::endl; std::cout << "************************* 测试关系类函数对象2 **************************" << std::endl << std::endl; std::cout << "equal_to<int>()(3, 5) = " << equal_to<int>()(3, 5) << std::endl << std::endl; std::cout << "not_equal_to<int>()(3, 5) = " << not_equal_to<int>()(3, 5) << std::endl << std::endl; std::cout << "greater<int>()(3, 5) = " << greater<int>()(3, 5) << std::endl << std::endl; std::cout << "greater_equal<int>()(3, 5) = " << greater_equal<int>()(3, 5) << std::endl << std::endl; std::cout << "less<int>()(3, 5) = " << less<int>()(3, 5) << std::endl << std::endl; std::cout << "less_equal<int>()(3, 5) = " << less_equal<int>()(3, 5) << std::endl << std::endl; system("pause"); return 0; }
测试环节的主要内容已在注释中说明
/******************************************************************* * Copyright(c) 2016 Chen Gonghao * All rights reserved. * * chengonghao@yeah.net * * 文件内容:测试逻辑运算类(Logical)函数对象(仿函数) ******************************************************************/ #include "stdafx.h" #include <iostream> #include "cgh_function_obj.h" int _tmain(int argc, _TCHAR* argv[]) { using namespace::CGH; logical_and<int> logical_and_obj; logical_or<int> logical_or_obj; logical_not<int> logical_not_obj; std::cout << std::endl; std::cout << "逻辑类函数对象共3个:logical_and、logical_or、logical_not" << std::endl << std::endl; std::cout << "************************ 测试逻辑类函数对象1 ***************************" << std::endl << std::endl; std::cout << "logical_and_obj(3, 5) = " << logical_and_obj(3, 5) << std::endl << std::endl; std::cout << "logical_or_obj(3, 5) = " << logical_or_obj(3, 5) << std::endl << std::endl; std::cout << "logical_not_obj(3) = " << logical_not_obj(3) << std::endl << std::endl; std::cout << "************************* 测试逻辑类函数对象2 **************************" << std::endl << std::endl; std::cout << "logical_and_obj<int>()(3, 5) = " << logical_and<int>()(3, 5) << std::endl << std::endl; std::cout << "logical_or_obj<int>()(3, 5) = " << logical_or<int>()(3, 5) << std::endl << std::endl; std::cout << "logical_not_obj<int>()(3) = " << logical_not<int>()(3) << std::endl << std::endl; system("pause"); return 0; }
标签:
原文地址:http://blog.csdn.net/chengonghao/article/details/51602592