重载“函数调用”有何用处?操作员?

发布于 2024-08-22 20:35:28 字数 223 浏览 5 评论 0原文

我最近发现,在 C++ 中,您可以以一种奇怪的方式重载“函数调用”运算符,其中您必须编写两对括号才能执行此操作:

class A { 
  int n;
public: 
  void operator ()() const; 
};

然后以这种方式使用它:

A a;
a();

这什么时候有用?

I recently discovered that in C++ you can overload the "function call" operator, in a strange way in which you have to write two pair of parenthesis to do so:

class A { 
  int n;
public: 
  void operator ()() const; 
};

And then use it this way:

A a;
a();

When is this useful?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

jJeQQOZ5 2024-08-29 20:35:28

这可用于创建 "functors",其行为类似于函数的对象:

class Multiplier {
public:
    Multiplier(int m): multiplier(m) {}
    int operator()(int x) { return multiplier * x; }
private:
    int multiplier;
};

Multiplier m(5);
cout << m(4) << endl;

上面的打印 20。上面链接的维基百科文章提供了更实质性的例子。

This can be used to create "functors", objects that act like functions:

class Multiplier {
public:
    Multiplier(int m): multiplier(m) {}
    int operator()(int x) { return multiplier * x; }
private:
    int multiplier;
};

Multiplier m(5);
cout << m(4) << endl;

The above prints 20. The Wikipedia article linked above gives more substantial examples.

好菇凉咱不稀罕他 2024-08-29 20:35:28

在开始使用模板之前,使用operator()只会带来语法上的好处。但是,当使用模板时,您可以以相同的方式对待实际函数和函子(充当函数的类)。

class scaled_sine
{
    explicit scaled_sine( float _m ) : m(_m) {}
    float operator()(float x) const { return sin(m*x); }
    float m;
};

template<typename T>
float evaluate_at( float x, const T& fn )
{
   return fn(x);
}

evaluate_at( 1.0, cos );
evaluate_at( 1.0, scaled_sine(3.0) );

There's little more than a syntactic gain in using operator() until you start using templates. But when using templates you can treat real functions and functors (classes acting as functions) the same way.

class scaled_sine
{
    explicit scaled_sine( float _m ) : m(_m) {}
    float operator()(float x) const { return sin(m*x); }
    float m;
};

template<typename T>
float evaluate_at( float x, const T& fn )
{
   return fn(x);
}

evaluate_at( 1.0, cos );
evaluate_at( 1.0, scaled_sine(3.0) );
回首观望 2024-08-29 20:35:28

使用模板实现的算法并不关心被调用的是函数还是仿函数,它关心的是语法。标准的(例如 for_each())或您自己的。函子可以拥有状态,并在被调用时执行各种操作。函数只能具有静态局部变量或全局变量的状态。

A algorithm implemented using a template doesn't care whether the thing being called is a function or a functor, it cares about the syntax. Either standard ones (e.g. for_each()) or your own. And functors can have state, and do all kinds of things when they are called. Functions can only have state with a static local variable, or global variables.

凉城已无爱 2024-08-29 20:35:28

例如,用于实现生成器:

// generator
struct Generator {
    int c = 0;

    virtual int operator()() {
        return c++;
    }
};

int sum(int n) {
    Generator g;

    int res = 0;
    for( int i = 0; i < n; i++ ) {
        res += g();
    }

    return res;
}

For example for implementing generators:

// generator
struct Generator {
    int c = 0;

    virtual int operator()() {
        return c++;
    }
};

int sum(int n) {
    Generator g;

    int res = 0;
    for( int i = 0; i < n; i++ ) {
        res += g();
    }

    return res;
}
烦人精 2024-08-29 20:35:28

如果您正在创建一个封装函数指针的类,这可能会使用法更加明显。

If you're making a class that encapsulates a function pointer, this might make the usage more obvious.

孤星 2024-08-29 20:35:28

编译器还可以内联函子和函数调用。但是,它不能内联函数指针。这样,当与标准 C++ 库算法一起使用时,使用函数调用运算符可以显着提高性能。

The compiler can also inline the functor and the function call. It cannot inline a function pointer, however. This way, using the function call operator can significantly improve performance when it is used for example with the standard C++ libary algorithms.

韵柒 2024-08-29 20:35:28

我看到了一种奇异用途的潜力:

假设您有未知类型的对象,并且必须声明相同类型的另一个变量,如下所示:

 auto c=decltype(a*b)(123);

当广泛使用这种模式时,decltype 变得非常烦人。
当使用某些智能类型系统时,可能会发生这种情况,该系统会根据参数类型自动创建函数和运算符的结果类型。

现在,如果该类型系统的每种类型的每个专精都配备了
operator() 的神奇定义是这样的:

template<????> class Num<???>{
    //specific implementation here
    constexpr auto operator()(auto...p){return Num(p...);}
}

不再需要 decltype() ,你可以简单地写:

auto c=(a*b)(123);

因为对象的operator()重定向到它自己类型的构造函数。

I see potential to yet one exotic use:

Suppose you have object of unknown type and have to declare another variable of same type, like this:

 auto c=decltype(a*b)(123);

When such pattern used extensively, decltype become very annoying.
This case can occur when using some smart type system that automatically invent type of result of functions and operators based on types of arguments.

Now, if each specialization of each type of that type system equipped with
magic definition of operator() like this:

template<????> class Num<???>{
    //specific implementation here
    constexpr auto operator()(auto...p){return Num(p...);}
}

decltype() no more needed, you can write simply:

auto c=(a*b)(123);

Because operator() of object redirects to constructor of its own type.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文