提高信号 库,它们载()操作人员。

这是一个《公约》在C++?回调,等等?

我已经看到这种代码中的一个共同的工人(他是一个很大的推动风扇)。所有提高善,这只有导致混乱,对我来说。

任何见解的原因,这种超负荷?

有帮助吗?

解决方案

其中一个主要的目标重载operator当()是创建一个仿函数。函子行为就像一个功能,但它有,它是有状态的优点,这意味着它可以保持数据反映了其呼叫之间的状态。

下面是一个简单的算符的示例:

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"

函子被重使用通用编程中使用。许多STL算法都写在一个非常普遍的方式,让你可以插入自己的函数/仿到算法。例如,该算法的std ::的for_each允许你的范围内的每个元素上应用的操作。它可以实现类似的东西:

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

您看到,因为它是由一个函数参数化这个算法是非常通用的。通过使用操作符(),这个功能可以让您使用仿函数或函数指针。下面是示出这两种可能性的示例:

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

关于你对运营商的问题()超载,以及是有可能。可以完美写具有几个括号运算函子,只要你尊重方法重载的基本规则(例如仅在返回类型超载是不可能的)。

其他提示

它允许一个类等的功能作用。我有一个日志类用它在呼叫应该是一个功能,但我想这个类的额外的好处。

所以是这样的:

logger.log("Log this message");

变成这样:

logger("Log this message");

许多人回答说,它使一个函子,瞒着一个很大的原因,一个仿函数比普通的旧功能较好。

答案是一个算符可以具有的状态。考虑求和函数 - 它需要保持一个运行总计

class Sum
{
public:
    Sum() : m_total(0)
    {
    }
    void operator()(int value)
    {
        m_total += value;
    }
    int m_total;
};

一个算符不是一个函数,所以不能过载它。结果 你的同事是正确的,虽然是运营商的重载()用于创建“函子” - 可以这样调用函数的对象。在使用模板期待“功能状”参数组合这可能是非常强大,因为对象和功能之间的区别变得模糊。

作为其他的海报说:函子有优势在于普通函数它们可以具有的状态。这种状态可以在单次迭代中使用(例如,以计算在一个容器中的所有元素的总和)或通过多次迭代(例如找到多个容器满足特定标准的所有元件)。

开始在你的代码更经常使用std::for_eachstd::find_if等,你就会明白为什么它的方便有重载()运算符的能力。它还允许仿函数和任务,有不会的在派生类的其他方法的名称冲突的明确的调用方法。

您还可以看看在 C ++常见问题的矩阵例如的。有做它很好的用途,但它当然取决于你所要完成的。

函子基本上像函数指针。它们一般被用来可拷贝(如函数指针),并以同样的方式作为函数指针调用。主要的好处是,当你有一个模板仿作品的算法,函数调用operator()可以内联。然而,函数指针仍然有效仿函数。

使用的操作员()形成 C++是相关的 编程功能 规范通常使用的一个类似的概念: 关闭.

一张强度我可以看到,然而,这可以被讨论的,是操作者()的签名的外观和行为在不同类型的相同。如果我们有一个类记者其中有一个成员方法报告(..),然后另一个类作家,其中有一个成员方法写(..),我们将不得不写适配器,如果我们想用这两个类为可能其他一些系统的模板组件。所有这将关心的是通过对字符串或者你有什么。如果不使用操作符()重载或写特殊类型的适配器,你不能做的东西像

T t;
t.write("Hello world");

,因为T具有一个要求,即有它接受任何隐式浇注料为const char *(或者更确切地说,为const char [])的成员函数调用写入。本例中的记者类没有这一点,所以具有T(模板参数)是记者将编译失败。

不过,据我可以看到,这将具有不同类型的工作

T t;
t("Hello world");

不过,它仍然明确要求类型T有这样的运营商定义的,所以我们还是有一个要求对T.就个人而言,我不认为它与过多函子奇怪的,因为它们通常使用,但我宁愿看到其他机制的这种行为。在如C#语言中,你可以只通过一个委托。我不是太熟悉C的成员函数指针,但我能想象你能做到有相同的行为以及。

除了语法糖行为,我真的没有看到运营商的优势重载执行这样的任务。

我相信有更多明知谁拥有更好的理由比我的人,但我想我会奠定了我的意见对你的其他人分享。

另一个同事指出,它可能是伪装函子对象作为功能的一种方式。例如,这样的:

my_functor();

真的是:

my_functor.operator()();

那么这意味这样的:

my_functor(int n, float f){ ... };

可用于重载这个问题,以及

my_functor.operator()(int n, float f){ ... };

其他职位已经做得很好描述符()是如何工作的,以及为什么它可能是有用的。

我最近一直在使用一些代码,使非常广泛的使用运营商的()。重载这个操作符的一个缺点是有些IDE变得不那么有效的工具,作为一个结果。在Visual Studio中,通常可以在方法调用右键单击转到方法定义和/或声明。不幸的是,VS是不是足够聪明的指数运营商()调用。特别是在所有的地方重载运算符()定义复杂的代码,它可以是很难弄清楚什么一段代码执行的地方。在一些情况下,我发现我已经运行的代码,并通过它跟踪找到什么实际运行。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top