std :: bind的奇怪行为

时间:2013-02-18 11:35:06

标签: c++ visual-c++ c++11

我使用这个std::bind绑定类外的函数并给出一个奇怪的行为。

它在某种程度上控制了私有成员变量的值。

//MClass.h
typedef std::function<void(void)> Action;

class MClass {

public:

  Action OnLeftClick;

//some other functions here

private:
  int totalContents;

  VScrollbar* _vscrollbar;

};

//MClass.cpp

在这种实现中它不会产生任何错误:

MClass::MClasss() {

  OnLefClick = std::bind(&VScrollbar::Scrolldown, this);

}

//but when I do this
//otherfile.h

MClass mclass;

void clickBar() {

  mclass.totalContents = 0;

}

void InitComponentns() {   

mclass.OnLeftClick = std::bind(clickBar, mclass);

}

每当我调用分配给OnLeftClick() clickBar()的函数时, totalContents的值不会更改为0(totalContents值会被MClass的其他函数递增)。

我在这里做错了吗?

2 个答案:

答案 0 :(得分:1)

this调用中的std::bind参数实际上是函数的第一个参数。对于成员函数,这必须是函数所属的类的实例,因为所有成员函数都有一个隐藏的第一个参数,即this指针。

因此,为了使您的代码正常工作,VScrollbar::Scrolldown的第一个参数必须是VScrollbar类的实例,而不是this中的MClass。像这样:

OnLefClick = std::bind(&VScrollbar::Scrolldown, _vscrollbar);

对于第二个std::bind调用,你应该只传递函数指针,因为它是一个不带参数的函数(隐藏或不隐藏):

mclass.OnLeftClick = std::bind(clickBar);

我对问题构建中的代码感到惊讶,因为totalContents成员变量是私有的,无法从clickBar函数访问。

答案 1 :(得分:1)

好吧,首先,你不能将mclass绑定到clickBar,因为该函数不带参数。您可以修改该函数以引用MClass

void clickBar(MClass& m) { m.totalContents = 42; }

其次,即使你可以,bind也可以复制mclass。您可以使用std::reference_wrapper来传递std::ref

#include <functional>

struct MClass { int totalContents = 0;};

void clickBar(MClass& m) { m.totalContents = 42; }

int main() {   
  MClass mclass;
  auto OnLeftClick = std::bind(clickBar, std::ref(mclass));
  OnLeftClick();
}