原创作品,转载请标明:http://blog.csdn.net/jackystudio/article/details/17435117
函数指针倒是蛮常见的,这函数对象又是什么呢?什么时候会用到函数对象?
1.什么是函数对象
函数对象就是定义了函数调用操作符,也就是operator()的对象。因此我们可以在定义函数调用操作符的时候,实现所需的函数功能。
2.示例
如上,其实最主要的还是operate()的定义,这和普通运算符的重载是一样的。
- template <typename T>
- class Max
- {
- public:
- T operator()(T a, T b){ return a>b?a:b;}
- };
- int _tmain(int argc, _TCHAR* argv[])
- {
- Max<int> intMax;
- cout<<intMax(50,60)<<endl;
- cout<<intMax.operator ()(50,60)<<endl;
- }
(1)程序定义了一个Max类(这里用了模版),重载了函数调用符,实现了函数功能:返回一个最大值。
(2)主函数中定义了一个Max类的对象,intMax,也就是函数对象。
(3)对函数调用符的使用,可以直接用括号,也可以用operate+括号的形式(从本质上来说,这是一个特殊的成员函数)。这和普通运算符的重载也是一样的。
3.什么时候用函数对象?
看了上面是例子,可能感觉怪怪的,明明一个函数就能搞定的事,为什么要搞个函数对象出来,函数对象到底用在哪?
正是因为函数对象是一个对象,所以它可以封装一些属性,比如函数调用的一些状态数据等等,而函数本身没有记忆功能,从这方面而言,函数比起函数对象弱爆了。函数对象就可以帮我们记住函数做了什么。
再看一个例子。
- //定义学生类,重载了输出操作符
- class Student
- {
- public:
- Student(string strName):name(strName){}
- friend ostream& operator<< (ostream& out, const Student& stu);
- private:
- string name;
- };
- ostream& operator<< (ostream& out, const Student& stu){out<<stu.name<<endl;return out;}
- //定义点名类,定义调用操作符实现点名功能,同时保存学生人数
- template <typename T>
- class NumberOff
- {
- public:
- NumberOff():m_count(0){}
- void operator()(const T& t)
- {
- cout<<t;
- m_count++;
- }
- int GetCount() const {return m_count;}
- private:
- int m_count;
- };
- int _tmain(int argc, _TCHAR* argv[])
- {
- NumberOff<Student> numberoff;//创建函数对象
- Student stu1("Jacky1");//创建Student对象
- Student stu2("Jacky2");
- Student stu3("Jacky3");
- numberoff(stu1);//点名
- numberoff(stu2);
- numberoff(stu3);
- cout<<"Total "<<numberoff.GetCount();//输出已点名人数
- }
输出:
Jacky1
Jacky2
Jacky3
Total 3
这样一来函数对象numberoff中的m_count就帮我们记住了函数调用的次数,也就是已点名学生的人数,就单这个例子而言完全可以写出一个更好的实现,这里举此例主要用于体现函数对象的优势。