你能帮我理解为什么这个绑定有效吗?

时间:2017-02-15 16:37:50

标签: c++ bind

我正在尝试用C ++理解bind和pre-fill函数。

Here's我的例子:

#include <iostream>
#include <functional>
#include <vector>

class Voice
{
public:
    double mValue;

private:
};

class VoiceManager
{
public:
    VoiceManager() { }
    ~VoiceManager() { }

    typedef std::function<void(Voice &)> VoiceChangerFunction;
    inline void UpdateVoices(VoiceChangerFunction callback) {
        for (int i = 0; i < mNumOfVoices; i++) {
            callback(mVoices[i]);
        }
    }
    static void SetValue(Voice &voice, unsigned int value) {
        voice.mValue = value;
        std::cout << voice.mValue << std::endl;
    }

private:
    static const int mNumOfVoices = 4;    
    Voice mVoices[mNumOfVoices];
};

int main()
{
    VoiceManager voiceManager;
    VoiceManager::VoiceChangerFunction callback;
    callback = std::bind(&VoiceManager::SetValue, std::placeholders::_1, 100);
    voiceManager.UpdateVoices(callback);
}

基本上,我创建了一个VoiceChangerFunction函数(对象),它将Voice &作为第一个参数并返回void

稍后,我bind一个函数,它将第一个参数作为我在调用它时给它的参数,以及我在绑定它时给出的另一个参数(100,我的例子。)

右?

我不明白的是:然后,这个函数被传递给UpdateVoices(),它将一个函数/对象作为输入,该函数/对象具有1个参数(Voice &),而不是我创建的2个参数绑定函数(Voice &unsigned int)。

它是如何运作的?

喜欢void VoiceChangerFunction(Voice &voice)并致电VoiceChangerFunction(Voice &voice, unsigned int value )

功能原型不同。我的意思是:我创建的回调bind不是VoiceChangerFunctions函数,因为需要更多参数

它如何工作/匹配?

3 个答案:

答案 0 :(得分:4)

这正是bindstd::function的美丽。您将回调定义为带有一个参数的函数,bind返回一个带有一个参数的函数对象。

这里的要点是它实际上调用了带2个参数的函数,但第二个是固定的,并且总是100(在你的情况下)。这是绑定器的唯一目的 - 提供一种使用一些固定值调用具有不同参数集的函数的方法。如果您要使用相同的参数集调用函数,则根本没有理由使用绑定器!

知道bind与lambdas类似,相同的代码可以写成 - 并且可能更清楚:

VoiceManager::VoiceChangerFunction callback;
callback = [](Voice& v) { VoiceManager::SetValue(v, 100); };
voiceManager.UpdateVoices(callback);

如果你很好奇它是如何工作的,你可能会尝试自己创建一个活页夹框架。如果你只是出于教育目的而不担心太多细节,那就不那么难了。

答案 1 :(得分:2)

当你绑定时,你正在创建一个只用rs!myField作为参数的新函数,这就是它的工作原理。

Voice

void a_func(int x) { return; } std::function<void(void)> new_func = std::bind(&a_func, 1); 现在具有new_func的签名,因此您可以将其传递到需要类型void(void)的函数的任何位置。

当您致电void(void时,它真的会调用new_func

答案 2 :(得分:2)

你对绑定的假设是错误的 您的绑定调用返回一个将接受一个参数的函数对象,即占位符。函数的另一个参数已经绑定到100。

一个小例子:

void foo(int i1, int i2) {};
std::function<void(int,int)> fn1 = std::bind(foo, std::placeholders::_1, std::placeholders::_2);
std::function<void(int)> fn1 = std::bind(foo, std::placeholders::_1, 1);
std::function<void()> fn1 = std::bind(foo, 1, 1);

bind将根据绑定和未绑定参数创建匹配函数。

<强>更新

编译器将根据绑定表达式和参数的副本生成结构。简化这样的事情(这不会编译):

struct Function_{
    void(*fn)(Voice &, unsigned int)
    unsigned int i_;

    Function_(void(*f)(Voice &, unsigned int), unsigned int i):fn(f),i_(i){}
    void operator()(Voice& v){
        fn(v, i_);
    }
}

fn是第一个参数,它是一个函数指针,而bound(100)是第二个参数。然后你只需要一些类型的擦除,你自己的绑定就可以了。