跳转到内容

函数对象

本页使用了标题或全文手工转换
维基百科,自由的百科全书

函数对象(function object)[note 1]是一个程序设计的对象允许被当作普通函数来调用。

函数对象与函数指针相比,有两个优点:第一是编译器可以内联执行函数对象的调用;第二是函数对象内部可以保持状态。

函数式程序设计语言还支持闭包,例如,first-class函数支持在其创建时用到的函数外定义的变量的值保持下来,成为一个函数闭包。

C++函数对象的实例

[编辑]

传统的C/C++函数指针:

#include <stdlib.h>

/* Callback function, returns < 0 if a < b, > 0 if a > b, 0 if a == b */
int compareInts(const void* a, const void* b)
{
  return *(const int *)a - *(const int *)b;
}
...
// prototype of qsort is
// void qsort(void *base, size_t nel, size_t width, int (*compar)(const void *, const void *));
...
int main(void)
{
    int items[] = { 4, 3, 1, 2 };
    qsort(items, sizeof(items) / sizeof(items[0]), sizeof(items[0]), compareInts);
    return 0;
}

C++中,函数对象是定义了函数调用运算符的类对象,称作class type functor

// comparator predicate: returns true if a < b, false otherwise
struct IntComparator
{
  bool operator()(const int &a, const int &b) const
  {
    return a < b;
  }
};
...
// An overload of std::sort is:
template <class RandomIt, class Compare>
void sort(RandomIt first, RandomIt last, Compare comp);
...
int main()
{
    std::vector<int> items { 4, 3, 1, 2 };
    std::sort(items.begin(), items.end(), IntComparator());
    return 0;
}

除了类类型函数对象,还有其他类型的函数对象,如使用成员函数指针或模板。C++11允许使用具有闭包功能的匿名函数。

C++ STL中的函数对象

[编辑]

C++的STL中的众多algorithm,非常依赖于函数对象处理容器的元素。因此,STL预定义了许多函数对象、谓词(predicate)、以及用于复合(composite)函数对象的binder、member function adapter、 pointer to function adapters、 negaters、 function objects base structure。由于STL中的algorithm使用函数对象作为参数时,一般都是传值调用,所以函数对象应该仔细设计其复制构造函数

预定义的函数对象

[编辑]

C++98在头文件functional中定义了下述函数对象: plus<type>() 结果为(param1 + param2) minus<type>() 结果为(param1 - param2) multiplies<type>() 结果为(param1 * param2) divides<type>() 结果为(param1 / param2) modulus<type>() 结果为(param1 % param2)

谓词(predicate)

[编辑]

返回布尔值(或者可以隐式转换为布尔值)的函数对象。用于STL中的algorithm时,谓词应该是无状态的( stateless)函数对象,即谓词的结果不依赖于内部的数据成员。这是因为STL中的algorithm不保证内部实现时对传入的谓词要复制多少次。 C++98在头文件functional中定义了下述谓词:

  • equal_to<type>() 结果为(param1 == param2)
  • not_equal_to<type>() 结果为(param1 != param2)
  • less<type>() 结果为 (param1 < param2)
  • greater<type>() 结果为(param1 > param2)
  • less_equal<type>() 结果为 (param1 <= param2)
  • greater_equal<type>() 结果为 (param1 >= param2)
  • logical_not<type>() 结果为 (!param1)
  • logical_and<type>() 结果为 (param1 && param2)
  • logical_or<type>() 结果为 (param1 || param2)

Function Adapter

[编辑]

用于组合(combine)、变换(transform)、操作(manipulate)函数对象、特定参数值、或者特定函数。进一步细分为:

Binder

[编辑]

C++98在头文件functional中定义了两个函数bind1st与bind2nd,返回值为binder1st、binder2nd类型。用于把二元函数对象分别绑定第一个、第二个参数后成为单元函数对象。

Negater

[编辑]

negate把一个作为谓词的函数对象取反。C++98在头文件functional中定义了两个函数not1与not2,返回值为unary_negate、binary_negate类型。

Member function adapter

[编辑]

Member function adapter用于把类的成员函数用作STL中的algorithm的参数。C++98在头文件functional中定义了:

  • 函数mem_fun,返回值为mem_fun_t类型,用于通过一个类对象指针来调用成员函数指针
  • 函数mem_fun_ref,返回值为mem_fun_ref_t类型,用于通过一个类对象引用来调用成员函数指针。

Pointer to function adapter

[编辑]

函数指针适配器(Pointer to function adapter)是把函数指针包装为一个函数对象,以便STL中的algorithm用函数对象作为统一的参数类型,不用再考虑以函数指针作为传入参数的情形。C++98在头文件functional中定义了:

  • 函数ptr_fun,返回值为pointer_to_unary_function类型,包装了一个单参数的函数指针。
  • 重载函数ptr_fun,返回值为pointer_to_binary_function类型,包装了一个双参数的函数指针。

Function Object Base

[编辑]

函数对象基类(Function Object Base)定义在头文件functional中,用作STL的预定义的与函数对象有关的各个类的基类,其中定义了几个类型,分别表示函数调用的各个参数类型、结果类型。

  • unary_function类,定义了2个类型:argument_type、result_type;
  • binary_function类,定义了3个类型:first_argument_type、second_argument_type、result_type;

Python

[编辑]

Python程序设计中,函数是作为头等对象(first-class object),可以如同普通的字符串、数值、list等对象那样操作。这使得大部分编写函数对象都是不必须的。

任何对象定义了__call__()方法,就具有了可以当作函数调用的语法。例如下面的做累加的类[2]

class Accumulator(object):
    def __init__(self, n):
        self.n = n
    def __call__(self, x):
        self.n += x
        return self.n

一个使用例子:

 >>> a = Accumulator(4)
 >>> a(5)
 9
 >>> a(2)
 11
 >>> b = Accumulator(42)
 >>> b(7)
 49

因为函数就是对象,可当作局部变量定义、确定其属性(内部状态)、作为别的函数的返回值。[3]例如:

def Accumulator(n):
    def inc(x):
        inc.n += x
        return inc.n
    inc.n = n
    return inc

Python 3中,可以用函数闭包来创建函数对象:

def Accumulator(n):
    def inc(x):
        nonlocal n
        n += x
        return n
    return inc

注释

[编辑]
  1. ^ In C++, a functionoid is an object that has one major method, and a functor is a special case of a functionoid.[1] They are similar to a function object, but not the same.

参考文献

[编辑]
  1. ^ 33.15: What's the difference between a functionoid and a functor? 互联网档案馆存檔,存档日期2004-10-13.
  2. ^ Accumulator Generator. [2013-08-03]. (原始内容存档于2020-11-09). 
  3. ^ Python reference manual - Function definitions. [2013-08-03]. (原始内容存档于2020-12-15). 

进一步阅读

[编辑]
  • David Vandevoorde & Nicolai M Josuttis (2006). C++ Templates: The Complete Guide, ISBN 0-201-73484-2: Specifically, chapter 22 is devoted to function objects.

外部链接

[编辑]
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy