C ++ Functors
我一直听到很多关于C ++函数的信息。 有人能给我一个概述,说明它们是什么以及它们会在什么情况下有用?
函子几乎就是定义operator()的类。 这可以让你创建“看起来像”一个函数的对象:
// this is a functor
struct add_x {
add_x(int x) : x(x) {}
int operator()(int y) const { return x + y; }
private:
int x;
};
// Now you can use it like this:
add_x add42(42); // create an instance of the functor class
int i = add42(8); // and "call" it
assert(i == 50); // and it added 42 to its argument
std::vector<int> in; // assume this contains a bunch of values)
std::vector<int> out(in.size());
// Pass a functor to std::transform, which calls the functor on every element
// in the input sequence, and stores the result to the output sequence
std::transform(in.begin(), in.end(), out.begin(), add_x(1));
assert(out[i] == in[i] + 1); // for all i
关于仿函数有很多好的东西。 一个是与常规功能不同,它们可以包含状态。 上面的例子创建了一个函数,它将42加到你给它的任何东西上。 但是这个值不是硬编码的,当我们创建我们的函数实例时,它被指定为构造函数参数。 我可以创建另一个加法器,只需通过调用具有不同值的构造函数就可以添加27个加法器。 这使得它们可以很好地定制。
如最后一行所示,您经常将函数作为参数传递给其他函数,例如std :: transform或其他标准库算法。 你可以用常规的函数指针来做同样的事情,除非像上面所说的那样,函数可以是“定制的”,因为它们包含状态,使它们更加灵活(如果我想使用函数指针,我必须编写一个函数在它的参数中加上了1,函数是一般的,并且添加了你初始化的任何东西),并且它们也可能更有效。 在上面的例子中,编译器确切地知道std::transform
应该调用哪个函数。 它应该调用add_x::operator()
。 这意味着它可以内联该函数调用。 这就像我手动调用矢量的每个值的函数一样高效。
如果我传递了一个函数指针,编译器不能立即看到它指向哪个函数,所以除非它执行一些相当复杂的全局优化,否则它必须在运行时取消引用指针,然后进行调用。
几乎没有。 你可以使用boost::function
来从函数和方法创建函子,如下所示:
class Foo
{
public:
void operator () (int i) { printf("Foo %d", i); }
};
void Bar(int i) { printf("Bar %d", i); }
Foo foo;
boost::function<void (int)> f(foo);//wrap functor
f(1);//prints "Foo 1"
boost::function<void (int)> b(&Bar);//wrap normal function
b(1);//prints "Bar 1"
你可以使用boost :: bind来为这个函子添加状态
boost::function<void ()> f1 = boost::bind(foo, 2);
f1();//no more argument, function argument stored in f1
//and this print "Foo 2" (:
//and normal function
boost::function<void ()> b1 = boost::bind(&Bar, 2);
b1();// print "Bar 2"
和最有用的,用boost :: bind和boost :: function你可以从类方法创建函数,实际上这是一个委托:
class SomeClass
{
std::string state_;
public:
SomeClass(const char* s) : state_(s) {}
void method( std::string param )
{
std::cout << state_ << param << std::endl;
}
};
SomeClass *inst = new SomeClass("Hi, i am ");
boost::function< void (std::string) > callback;
callback = boost::bind(&SomeClass::method, inst, _1);//create delegate
//_1 is a placeholder it holds plase for parameter
callback("useless");//prints "Hi, i am useless"
您可以创建函子列表或向量
std::list< boost::function<void (EventArg e)> > events;
//add some events
....
//call them
std::for_each(
events.begin(), events.end(),
boost::bind( boost::apply<void>(), _1, e));
所有这些东西都有一个问题,编译器错误消息不是人类可读的:)
Functor是一个功能类似的对象。 基本上,定义了operator()
。
class MyFunctor
{
public:
int operator()(int x) { return x * 2;}
}
MyFunctor doubler;
int x = doubler(5);
真正的好处是一个仿函数可以保持状态。
class Matcher
{
int target;
public:
Matcher(int m) : target(m) {}
bool operator()(int x) { return x == target;}
}
Matcher Is5(5);
if (Is5(n)) // same as if (n == 5)
{ ....}
链接地址: http://www.djcxy.com/p/24565.html
上一篇: C++ Functors