定义函数对象

2016-01-29 12:18 0 1 收藏

定义函数对象,定义函数对象

【 tulaoshi.com - C语言心得技巧 】

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

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

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

class Negate 
{
public: 
int operator() (int n) { return -n;} 
};

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

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

使用函数对象

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

#include <iostream>
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 <class T> 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 <functional> // for greater<> and less<>
#include <algorithm> //for sort() 
#include

来源:https://www.tulaoshi.com/n/20160129/1485505.html

延伸阅读
标签: Web开发
From: JavaEye.com prototype提供了一套JavaScript面向对象基础设施,我们可以使用它来进行面向对象编程,定义对象类型方式如下:  var Person = Class.create(); Person.prototype = {  initialize : function(name, age) {  this.name = na...
标签: Web开发
无标题页 [Ctrl+A 全选 注:如需引入外部Js需刷新才能执行]
标签: PHP
  每次编写列表性质的页面,几乎都要写上一段分页的程序。最近小阳终于决心一劳永逸——自定义一个分页函数,并保存在“pageft.php”文件里。要用到分页的地方,就直接包含“pageft.php”文件,并调用这个函数就行了。小阳在编写这个函数时,尽量注意了程序的可移植性和易用性,下面就是小阳编写的函数: 好,分页函数已经...
标签: Web开发
From: JavaEye.com prototype提供了一套JavaScript面向对象基础设施,我们可以使用它来进行面向对象编程,定义对象类型方式如下: var Person = Class.create(); Person.prototype = {  initialize : function(name, age) {  this.name = name;  this.age = age;  },  toString : function() {  document.writel...
标签: Web开发
一、jQuery 核心函数 首先介绍 jQuery 的几个核心函数,在 jQuery 中它们起着至关重要的作用,在实际的前端开发过程中用到最多的也是它们。 1、jQuery(elements) 将一个或多个DOM元素转化为jQuery对象。 这个函数也可以接收XML文档和Window对象(虽然它们不是DOM元素)作为有效的参数。 返回值:jQuery 对象 参数 ...

经验教程

202

收藏

53
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部