zoukankan      html  css  js  c++  java
  • 仿函数

    仿函数的通俗定义:仿函数(functor)又称为函数对象(function object)是一个能行使函数功能的类。

    仿函数的语法几乎和我们普通的函数调用一样,不过作为仿函数的类,都必须重载operator()运算符

     class Func
    {
         public:
             void operator() (const string& str) const 
            {
                 cout<<str<<endl;
             }
     };  
    1 Func myFunc;
    2 myFunc("helloworld!");
    >>>helloworld!

     函数(functor)又称之为函数对象(function object),其实就是重载了operator()操作符的struct或class,没有什么特别的地方。仿函数(functor)使一个类的使用看上去象一个函数,这个类就有了类似函数的行为,就是一个仿函数类了。

            如下面的代码定义了一个二元的仿函数(有两个参数):

    struct IntLess
    {
    	bool operator()(int _left, int _right) const
    	{
    		return _left<_right;
    	}
    };
    

            为什么要使用仿函数呢 ?
            1)仿函数比一般的函数灵活。        

            2)仿函数有类型识别,可以作为模板参数。

            3)执行速度上仿函数比函数和指针要更快的。

            怎么使用仿函数?

            除了在stl里,别的地方你很少会看到仿函数的身影。而在stl里仿函数最常用的就是作为函数的参数,或者模板的参数。在stl里有自己预定义的仿函数,比如所有的运算符,=,-,*,/,比如比较符号<、>、<=、>=等。stl中的'<'仿函数是less:

    		// TEMPLATE STRUCT less
    template<class _Ty>
    	struct less	: public binary_function<_Ty, _Ty, bool>
    	{	// functor for operator<
    	bool operator()(const _Ty& _Left, const _Ty& _Right) const
    		{	// apply operator< to operands
    		return (_Left < _Right);
    		}
    	};

    从上面的定义可以看出,less就是一个含有模板的结构图,并在结构体内重载了operator()运算符。再看发现less是从binary_function<...>继承而来的,binary_function的定义如下:

    		// TEMPLATE STRUCT greater
    template<class _Ty>
    	struct greater
    		: public binary_function<_Ty, _Ty, bool>
    	{	// functor for operator>
    	bool operator()(const _Ty& _Left, const _Ty& _Right) const
    		{	// apply operator> to operands
    		return (_Left > _Right);
    		}
    	};

            其 实binary_function只是做一些类型声明而已,别的什么也没做,但是在stl里为什么要做这些呢?如果你要阅读过stl的源码,你就会发现, 这样的用法很多,其实没有别的目的,就是为了方便,安全,可复用性等。但是既然stl里面内定如此了,所以作为程序员你必须要遵循这个规则!否则就别想安 全的使用stl!

           下面看一个简单的仿函数应用的例子:

    // 仿函数(functor或function object)
    class Person
    {
    public:
    	Person();
    	//~Person();
    	Person(string _firstname, string _lastname)
    	{
    		this->FirstName = _firstname;
    		this->LastName = _lastname;
    	}
    public:
    	string FirstName;
    	string LastName;
    	// additional information
    };
    
    class PersonCriterion
    {
    public:
    	bool operator()(const Person& p1, const Person& p2)
    	{
    		return p1.LastName < p2.LastName ||(!(p2.LastName<p1.LastName) && p1.FirstName<p2.FirstName);
    	}
    };
    
    int main( int argc, char* argv[])
    {
    	set<Person, PersonCriterion> colls;
    	colls.insert(Person("Tom","James"));
    	colls.insert(Person("Mike","James"));
    	colls.insert(Person("Jane","Bush"));
    	colls.insert(Person("Bill","Gates"));
    
    	std::set<Person, PersonCriterion>::iterator iter;
    	for ( iter = colls.begin(); iter!=colls.end(); ++iter)
    	{		
    		Person p = (Person)(*iter);		
    
    		cout<< p.FirstName<<"  "<<p.LastName<<endl;
    	}		
    	getchar();
    	return 1;
    }
    

           在上面的例子中,定义了一个Person类,包含2个成员变量FirstName和LastName,并定义了一个PersonCriterion类来对Person进行排序。PersonCriterion定义了一个operator()用于比较两个人的姓,如果姓相等,再比较其名。这样coll的构造函数就会自动产生PersonCriterion的一个实体,并将所有的元素按此进行排序。

            注意,在这里PersonCriterion是一个类,我们把它作为set的template参数,而一般的函数却不能做到这一点,进一步凸显了仿函数的优势。

  • 相关阅读:
    qt鼠标事件总结(坐标,跟踪,点击判断)
    从零开始学C++之RTTI、dynamic_cast、typeid、类与类之间的关系uml
    前端篇: 前端演进史
    找一款防文件或文件夹误删除,移动,修改的软件
    yyyy
    盘点我用过的那些网盘(那些年,我们一起玩的网盘)
    Win8/8.1/10获得完整管理员权限的方法
    [置顶] IT老男人读《因为痛,所以叫青春》
    dddd
    用JUNCTION映射文件夹内容 解决多系统跑同一个虚拟机而共享文件夹路径不同的问题
  • 原文地址:https://www.cnblogs.com/pjl1119/p/9681468.html
Copyright © 2011-2022 走看看