Function Objects(函数对象)

本文介绍了C++中的函数对象(Function Objects),强调它们比函数指针更为一般化,可以重载操作符`operator()`。通过示例展示了如何创建和使用函数对象,包括带有成员变量和成员函数的情况。还探讨了函数对象的关联类型,如参数类型和返回值类型,并提到了unary_function和binary_function基类。文章最后讨论了如何为函数对象获取相关类型的策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Function Objects(函数对象)
  在了解函数对象的定义前,我们先来看一个例子。
  我们考虑一个特殊的查找函数:

template <class Iterator, class Predicate>
Iterator find_if(Iterator first, Iterator last, Predicate pred)
{
    while(first!=last && !pred(*first))
    ++first;
}

  这个find_if跟一般查找某个元素的find非常相似,只不过它是查找满足pred条件的那个元素,显然它比find更加一般化。我们可以看到,这里的pred并非声明为一个函数指针(这是C的习惯做法),而是声明为一个模板参数Predicate,显然它可以包括函数指针,但是它比函数指针更加一般化。
  那么,这个Predicate可以是一个对象吗?当然可以,因为function call操作符operator()可以重载,你可以把这个对象传给find_if当参数,而像这样的对象就是函数对象(当然,函数指针是最特殊的函数对象),让我们来看一个例子:

template <class Number>
struct even{
    bool operator(Number x) const
  { 
    return (x&1)==0;
  }
};

  那么我们查找第一个偶数可以这样写:
  find_if(f,l,even());
  这里even是一个class,调用了其构造函数,把它看做一个用类包装的函数好了,只不过它比一般的函数更灵活,因为它可以搭配使用任何整数类型,并不只是int,也更加有效率,因为这里的operator()是inline,不需任何函数调用。
  当然,函数对象也可以像一般class一样拥有成员变量和成员函数,让我们来看一个例子,本例子的测试条件就是元素的last_name字段等于某一特定值:

template <class T>
struct last_name_is{
    T value;
    last_name_is(const T& val):value(val){};
    bool operator(const Person& p){
        return p.last_name == value;
    }
};

  调用函数为:
  Find_if(f,l,last_name_is(“kangkang”));
  很显然,任何函数对象的基本条件只是:如果f是一个函数对象,就可以使用operator()。

  双参函数对象:让我们直接看例子:

template<class T>
class Add{
public:
    T operator() (T& t1, T& t2)
    {
        return t1+t2;
    }
};
cout<< Add<int>(0,8);
cout<< Add<double>(3.2,19.8);

  可以看到,函数对象的行为和函数一致,即是说可以像调用函数一样来使用函数对象,如参数传递、返回值等。

  函数对象(Function Objects)(2):Associated type
  从前面的例子我们可以看到,函数对象有两种很重要的相关类型:参数类型,返回值类型,前面的class even就有一个参数类型T和一个返回值类型bool,这两种类型也是普通函数最重要的两种类型。
  和Iterator一样,获取这些相关类型是非常重要的,同样,我们可以向Iterator一样,拥有嵌套类型。像Iterator一样,我们可以定义空的基类,这里我们定义基类unary_function和binary_function,分别对应单参和双参。

template<class Arg, class Res>
struct unary_function //单参函数对象基类
{
   typedef Arg argument_type;
   typedef Result result_type;
};
template<class Arg1, class Arg2, class Res>
struct binary_function //双参函数对象基类
{
   typedef Arg1 first_argument_type;
   typedef Arg2 second_argument_type;
   typedef Result  result_type;
};

  那么修改之前的even有两种方法:
  (1) 明确指出两种相关类型:
  (2) 更简单的继承基类unary_function

Template <class Numble>
struct even: public unary_function<Number,bool>
{
    Bool operator()(Number x) const {return (x&1)==0;}
}

  但是对于函数指针,它是一种内建类型,无法定义嵌套类型,那么,我们是否可以像解决Iterator问题一样解决这个问题,在外面包一层,定义一个traits class,名为unary_function_traits和binary_function_traits。但事实上,STL并没有这样的东东,可能是函数对象还没有重要到像Iterator那样的程度,没必要为每个函数对象都提供获取相关类型的方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

One2zeror

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值