刚开始看到这个名字,还以为是函数呢,谁知道大错特错!
顾名思义,就是在某种方式上表现得象一个函数的对象。典型地,它是指一个类的实例,这
个类定义了应用操作符operator()。
函数对象是比函数更加通用的概念,因为函数对象可以定义跨越多次调用的可持久的部分
(类似静态局部变量),同时又能够从对象的外面进行初始化和检查(和静态局部变量不同)。
例如:
class Sum {
int val;
public:
Sum(int i) :val(i) { }
operator int() const { return val; } // 取得值
int operator()(int i) { return val+=i; } // 应用
};
void f(vector v)
{
Sum s = 0; // initial value 0
s = for_each((), (), s); // 求所有元素的和
cout << "the sum is " << s << "/n";
//或者甚至:
cout << "the sum is " << for_each((), (), Sum(0)) <<
"/n";
}
注意一个拥有应用操作符的函数对象可以被完美地内联化(inline),因为它没有涉及到
任何指针,后者可能导致拒绝优化。与之形成对比的是,现有的优化器几乎不能(或者完全
不能?)将一个通过函数指针的调用内联化。
在标准库中,函数对象被广泛地使用以获得弹性。
它有什么用呢?
函数对象用处相当大,我也是一新手,不能一一道来,只能就我知道的说说。
一、可以用(而且提倡、建议)函数对象来代替函数指针。
函数指针用的好好的,干吗有造出来一个函数对象呢?C++ 疯了?没有疯,明智的很。因为函数对象与函数指针相比有N多优点:
(1)、函数对象可以在内部修改而不用改动外部接口。。。。。。这优点很明显了吧。(什么灵活啊、富有弹性啊等等)
(2)、函数对象具备有存储先前调用结果的数据成员。它可以在使用前保存,使用后你想取出都没问题。而普通函数则需要将先前调用的结果存储在全程或者本地静态变量中,但是全程或者本地静态变量有某些我们不愿意看到的缺陷。
(3)、函数对象可内联编译,性能好。用函数指针几乎不可能。
二、函数对象所完成的功能不只是“函数的功能”
与原有的函数指针相比,它可以很好的用于类方法。而函数指针差矣。现举例说明:
普通函数指针:
typedef int (*PFUNC)(char*, int);
int MyFunc(char* name, int value);
PFUNC pMyFunc = MyFunc;
int ret = (*pMyFunc)("hello", 66);
类方法指针:
typedef int (CMyClass::*pfunc)(char*, int); //必须是知道要指向的是CMyClass类的方法
int CMyClass::MyFunc(char* name, int value);
CMyClass me;
pfunc pMyFunc = ;
(*pMyFunc)("hello", 66); // 错误!如果MyFunc中用到了成员变量就访问无效
(me.*pMyFunc)("hello", 66); // 必须加 me.*才能正确调用
函数类:
class CFunc
{
public:
typedef int (CObject::*ftype)(char*, int); //函数类型
CFunc(CObject* _obj, ftype _func):obj(_obj),func(_func) {};
CObject* obj;
ftype func;
int operator()(char* name, int value)
{
return (obj->*func)(name, value); // operator() 调用原对象的类方法
};
};
class CMyClass
{
public:
int CMyClass::MyFunc(char* name, int value)
{
return strlen(name)+value;
};
};
CMyClass me;
CFunc pMyFunc((CObject*)&me, (CFunc::ftype)CMyClass::MyFunc);
pMyFunc("myname", 88);
三、函数对象通常不定义构造函数和析构函数,所以在构造和析构时不会发生任何问题,避免了函数调用的运行时问题。
四、模版函数对象使函数对象具有通用性,这也是它的优势之一。
class Generic
{
public:
template <class T> T operator() (T t) const {return -t;}
};
int main()
{
Generic negate;
cout<< negate(5.3333); // double
cout<< negate(10000000000i64); // __int64
}
如果用普通的回调函数实现上述的灵活性是相当困难的。
如何使用函数对象?
/winc_co/archive/2007/06/09/