STL函数对象

原文:STL Function objects

作者:Chris Losinger.

原文地址:http://www.codeproject.com/vcpp/stl/functor.asp

翻译:jans

这篇文章讨论了一个简单的STL函数对象,一个函数对象函数被称为算法,也就是说它们和标准C库函数相比,它们更为通用。STL算法通过重载operator()函数实现为模板类或模板函数。这些类用于创建函数对象,对容器中的数据进行各种各样的操作。函数对象可以维护自己的状态。这一点对于不仅仅是比大小的情形特别有用。

std::sort

就像C语言中古老的qsort函数,std::sort函数可以接受一个比较函数参数,这个函数在数组中两个对象进行比较时被调用。典型的比较函数如下:

bool compare_myObjects(const CMyObject &a, const CMyObject &b)
{
    return a.x < b.x;
}
你可以对下面的对象数组进行排序:

// declare the vector

vector <CMyObject> myArray;

... initialize the vector
.
.
.
// sort it
std::sort(myArray.begin(), myArray.end(), compare_myObjects);

99%情况下,这种方式工作的都很好。

下面我们讨论其它1%的情况
如果你需要进行排序的不是基于一个数组中的两个对象,如果排序时对象间的比较还要访问其它一些非全局变量,或者是你要排序的数组基于另一个数组的内容? 当然用一些全局变量,你可做到这些,但是那样不是好的编程风格,函数对象,可以帮助你用面向对象的C++风格做到这些。

binary_function

binary_function是一个模板,可以允许你定义一个类,其行为像一个二元操作符,它接受两个参数,类型A,B返回类型C,它就像一个类,当用在函数中时,比如std::sort
也就是是一个函数。你可以在类中保存一些状态信息,用来比较或者作为二元操作符调用,就像上面的compare_myObjects函数

对基于另一个数组之上的数组的排序

举一个下面的例子,有两个数组:一个数组叫employee对象,另一个是整数数组,这个整数数组是employee对象数组中对象的索引数组,我们将对这个数组进行排序。假定我们无法直接对employee对象数组进行排序,比如因为某种原因我们不能破坏employee对象数组中对象元素的顺序。
首先,定义employee类:
class employee
{
public:
   int m_salary;
   string m_name;
};

其次,定义一个binary function
//这个类就是函数对象类
//定义对employee数组的引用
class employeecomp : public std::binary_function<int,int,bool>
{
   // the vector reference
   const vector<employee> &m_employees;

public:
   // 构造时对employee数组引用
   employeecomp( const vector<employee> & employees ) : m_employees(employees) {}

   // 比较操作符. 将被std::sort引用,用来进行两个元素的比较,根据输入的值a,b返回比较结果
   bool operator()(int a, int b) const
   {
      //输入的值是employees数组中元素的索引,然后进行比较的是根据索引得到的employe的m_salary变量
      return (m_employees.at(a).m_salary) < (m_employees.at(b).m_salary);
   }
};

使用一下我们定义的函数对象:

先初始化两个数组

//我们将要进行排序的索引数组
vector<int> indexVector;

// employee数组
vector<employee> employeeVector;

//初始化索引数组
for (int i=0; i < 4; i++)
{
   indexVector.push_back(i);
}

//初始化employee数组,为其增加内容
employee h;

h.m_salary = 0;
h.m_name = "fred";
employeeVector.push_back(h);

h.m_salary = 99;
h.m_name = "ethel";
employeeVector.push_back(h);

h.m_salary = 32;
h.m_name = "ricky";
employeeVector.push_back(h);

h.m_salary = 23;
h.m_name = "lucy";
employeeVector.push_back(h);

排序前我们看一下indexVector数组的内容:


printf("Before sorting/n");
vector<int>::iterator it;
i = 0;
for (it = indexVector.begin(); it != indexVector.end(); it++)
{
   printf("indexVector[%d] = %d/n", i, (*it));
   i++;
}

所有排序要的东西都在这儿了,前两个参数就是我们要排序的数组的起点和终点,第三个参数就是所谓的断言函数. 这种情况下, 断言就是一个刚刚初始化的包含了employe数组的employeecomp对象. 对于每次比较std::sort需要先调用Pr(x,y), Pr是比较函数.比较函数就是 employeecomp对象的"()"操作符,x和y就是indexVector里面的两个元素.


std::sort(indexVector.begin(),
         indexVector.end(),
         employeecomp(employeeVector)); // employeecomp需要初始化其中employee数组

//排序后我们看一下indexVector数组的内容:
printf("After sorting/n");
i = 0;
for (it = indexVector.begin(); it != indexVector.end(); it++)
{
   printf("indexVector[%d] = %d/n", i, (*it));
   i++;
}

排序前索引数组内容为:
indexVector[0] = 0
indexVector[1] = 1
indexVector[2] = 2
indexVector[3] = 3

排序后:
indexVector[0] = 0
indexVector[1] = 3
indexVector[2] = 2
indexVector[3] = 1

你可以看到indexVector已经变了.但是发生了怎么样的改变呢?
indexVector数组中的值现在表示的是employeeVector数组的索引,按照salary递增排序. 但是 employeeVector数组并没改变。
这个是一个基本的关于函数操作符的例子,尽管如此,它在一些情形下仍然是一个非常有用的技术,因为你可以基于binary_function 创建一个全功能的类,无论其有多么复杂性(例如可以对一个函数对象的数组排序)而且也不仅仅限于std:sort函数中使用,还可用于STL中的其他算法。

感谢你的关注!

 


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值