我正在尝试用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
函数,因为需要更多参数。
它如何工作/匹配?
答案 0 :(得分:4)
这正是bind
和std::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)是第二个参数。然后你只需要一些类型的擦除,你自己的绑定就可以了。