简体   繁体   中英

strange behavior of std::bind

I am using this std::bind to bind function outside the class and gives a strange behavior.

It somewhat controls the value of private member variables.

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

class MClass {

public:

  Action OnLeftClick;

//some other functions here

private:
  int totalContents;

  VScrollbar* _vscrollbar;

};

//MClass.cpp

in this kind of implementation it does not make any bug:

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);

}

and whenever I call the function assigned to OnLeftClick() that is clickBar() , the value of totalContents does not change in value to 0 (totalContents value is incremented by other functions of MClass).

am I doing something wrong here?

The this argument in the std::bind call is actually the first argument to the function. For member functions this has to be an instance of the class the function is a member of, as all member function has a hidden first argument that is the this pointer.

So for your code to work, the first argument to the VScrollbar::Scrolldown has to be an instance of a VScrollbar class, not this in the MClass . Like so:

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

For the second std::bind call, you should only pass it the function pointer, as it's a function that takes no arguments (hidden or not):

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

I'm surprised the code in the question builds though, as the totalContents member variable is private, and can't be accessed from the clickBar function.

Well, for starters, you cannot bind mclass to clickBar, since the function takes no arguments. You could modify the function to take a reference to an MClass :

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

Second, even if you could, bind would make a copy of mclass. You could pass an std::reference_wrapper instead, using 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();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM