【zz】函数对象

简介:

尽管函数指针被广泛用于实现函数回调,但C++还提供了一个重要的实现回调函数的方法,那就是函数对象。函数对象(也称“算符”)是重载了“()”操作符的普通类对象。因此从语法上讲,函数对象与普通的函数行为类似。


用函数对象代替函数指针有几个优点,首先,因为对象可以在内部修改而不用改动外部接口,因此设计更灵活,更富有弹性。函数对象也具备有存储先前调用结果的数据成员。在使用普通函数时需要将先前调用的结果存储在全程或者本地静态变量中,但是全程或者本地静态变量有某些我们不愿意看到的缺陷。

其次,在函数对象中编译器能实现内联调用,从而更进一步增强了性能。这在函数指针中几乎是不可能实现的。


下面举例说明如何定义和使用函数对象。首先,声明一个普通的类并重载“()”操作符:


class Negate

{

public:

int operator() (int n) { return -n;}

};


重载操作语句中,记住第一个圆括弧总是空的,因为它代表重载的操作符名;第二个圆括弧是参数列表。一般在重载操作符时,参数数量是固定的,而重载“()”操作符时有所不同,它可以有任意多个参数。


因为在Negate中内建的操作是一元的(只有一个操作数),重载的“()”操作符也只有一个参数。返回类型与参数类型相同-本例中为int。函数返回与参数符号相反的整数。


使用函数对象


我们现在定义一个叫Callback()的函数来测试函数对象。Callback()有两个参数:一个为int一个是对类Negate的引用。Callback()将函数对象neg作为一个普通的函数名:


#include

using std::cout;


void Callback(int n, Negate & neg)

{

int val = neg(n); //调用重载的操作符“()”

cout << val;

}


不要的代码中,注意neg是对象,而不是函数。编译器将语句


int val = neg(n);


转化为


int val = neg.operator()(n);


通常,函数对象不定义构造函数和析构函数。因此,在创建和销毁过程中就不会发生任何问题。前面曾提到过,编译器能内联重载的操作符代码,所以就避免了与函数调用相关的运行时问题。


为了完成上面个例子,我们用主函数main()实现Callback()的参数传递:


int main()

{

Callback(5, Negate() ); //输出 -5

}


本例传递整数5和一个临时Negate对象到Callback(),然后程序输出-5。


模板函数对象


从上面的例子中可以看出,其数据类型被限制在int,而通用性是函数对象的优势之一,如何创建具有通用性的函数对象呢?方法是使用模板,也就是将重载的操作符“()”定义为类成员模板,以便函数对象适用于任何数据类型:如double,_int64或char:


class GenericNegate

{

public:

template T operator() (T t) const {return -t;}

};


int main()

{

GenericNegate negate;

cout<< negate(5.3333); // double

cout<< negate(10000000000i64); // __int64

}


如果用普通的回调函数实现上述的灵活性是相当困难的。


标准库中函数对象


C++标准库定义了几个有用的函数对象,它们可以被放到STL算法中。例如,sort()算法以判断对象(predicate object)作为其第三个参数。判断对象是一个返回Boolean型结果的模板化的函数对象。可以向sort()传递greater<>或者less<>来强行实现排序的升序或降序:


#include // for greater<> and less<>

#include //for sort()

#include

using namespace std;


int main()

{

vector vi;

//..填充向量

sort(vi.begin(), vi.end(), greater() );//降序( descending )

sort(vi.begin(), vi.end(), less() ); //升序 ( ascending )

}

目录
相关文章
|
5月前
|
JavaScript 前端开发
Symbol有哪些常用的内置方法
Symbol有哪些常用的内置方法
|
11月前
|
C++
38 C++ - 函数调用符号()重载
38 C++ - 函数调用符号()重载
32 0
【C++】 --- 函数对象
【C++】 --- 函数对象
38 0
|
存储 Python
print()函数和变量与赋值
相信大家看了昨天的教程都已经将python成功的安装到自己的电脑上了,那接下来我们今天就来学习我们python中的第一个知识点——print()函数
182 0
print()函数和变量与赋值
尽量以non-member non-friend函数替换成员函数
尽量以non-member non-friend函数替换成员函数
156 0
|
C++ 编译器
关于C++中操作符重载的疑问 :四个运算符=, -&gt;, [], ()不可以重载为全局函数(友员函数)
转载自:http://blog.csdn.net/u014610226/article/details/47679323     以下是对C++中不能重载为友元函数的四个运算符进行了详细的分析介绍,需要的朋友可以过来参考下   C++规定有四个运算符 =, ->, [], ()不可以是全局域中的重载(即不能重载为友员函数),这是为什么呢?现在先说说赋值运算符“=”的重载C++规定赋值运算符“=”只能重载为类的非静态成员函数,而不可以重载为类的友元函数。
1687 0