Why override operator()?

2019-01-03 11:50发布

In the Boost Signals library, they are overloading the () operator.

Is this a convention in C++? For callbacks, etc.?

I have seen this in code of a co-worker (who happens to be a big Boost fan). Of all the Boost goodness out there, this has only led to confusion for me.

Any insight as to the reason for this overload?

11条回答
Rolldiameter
2楼-- · 2019-01-03 12:28

Functors are basically like function pointers. They are generally intended to be copyable (like function pointers) and invoked in the same way as function pointers. The main benefit is that when you have an algorithm that works with a templated functor, the function call to operator() can be inlined. However, function pointers are still valid functors.

查看更多
在下西门庆
3楼-- · 2019-01-03 12:36

Many have answered that it makes a functor, without telling one big reason why a functor is better than a plain old function.

The answer is that a functor can have state. Consider a summing function - it needs to keep a running total.

class Sum
{
public:
    Sum() : m_total(0)
    {
    }
    void operator()(int value)
    {
        m_total += value;
    }
    int m_total;
};
查看更多
时光不老,我们不散
4楼-- · 2019-01-03 12:39

A functor is not a function, so you cannot overload it.
Your co-worker is correct though that the overloading of operator() is used to create "functors" - objects that can be called like functions. In combination with templates expecting "function-like" arguments this can be quite powerful because the distinction between an object and a function becomes blurred.

As other posters have said: functors have an advantage over plain functions in that they can have state. This state can be used over a single iteration (for example to calculate the sum of all elements in a container) or over multiple iterations (for example to find all elements in multiple containers satisfying particular criteria).

查看更多
Animai°情兽
5楼-- · 2019-01-03 12:40

It allows a class to act like a function. I have used it in a logging class where the call should be a function but i wanted the extra benefit of the class.

so something like this:

logger.log("Log this message");

turns into this:

logger("Log this message");
查看更多
劳资没心,怎么记你
6楼-- · 2019-01-03 12:46

The use of operator() to form functors in C++ is related to functional programming paradigms that usually make use of a similar concept: closures.

查看更多
smile是对你的礼貌
7楼-- · 2019-01-03 12:47

One of the primary goal when overloading operator() is to create a functor. A functor acts just like a function, but it has the advantages that it is stateful, meaning it can keep data reflecting its state between calls.

Here is a simple functor example :

struct Accumulator
{
    int counter = 0;
    int operator()(int i) { return counter += i; }
}
...
Accumulator acc;
cout << acc(10) << endl; //prints "10"
cout << acc(20) << endl; //prints "30"

Functors are heavily used with generic programming. Many STL algorithms are written in a very general way, so that you can plug-in your own function/functor into the algorithm. For example, the algorithm std::for_each allows you to apply an operation on each element of a range. It could be implemented something like that :

template <typename InputIterator, typename Functor>
void for_each(InputIterator first, InputIterator last, Functor f)
{
    while (first != last) f(*first++);
}

You see that this algorithm is very generic since it is parametrized by a function. By using the operator(), this function lets you use either a functor or a function pointer. Here's an example showing both possibilities :

void print(int i) { std::cout << i << std::endl; }
...    
std::vector<int> vec;
// Fill vec

// Using a functor
Accumulator acc;
std::for_each(vec.begin(), vec.end(), acc);
// acc.counter contains the sum of all elements of the vector

// Using a function pointer
std::for_each(vec.begin(), vec.end(), print); // prints all elements

Concerning your question about operator() overloading, well yes it is possible. You can perfectly write a functor that has several parentheses operator, as long as you respect the basic rules of method overloading (e.g. overloading only on the return type is not possible).

查看更多
登录 后发表回答