tags:

views:

183

answers:

7

Is there a function in c++ that when a variable got changed it automaticly call a function?

+7  A: 

In one word; no.

But what you should do is wrap the variable into a class (i'm not going to suggest operator overloading), and change it via a set(...) function. Then you simply call the function from the set function.

Viktor Sehr
Uhm, why the -1?
Viktor Sehr
In one word: yes. With a moderate amount of effort, a listener can monitor the variable for changes in a multi-threaded program and call functions accordingly. Even in a non-multithreaded system it could work, although it would be a bit of a hack. I'm not saying I recommend it, as the setter option is (probably) better, but to say it can't be done is simply incorrect.
glowcoder
@glow That doesn't sound anything like a function included with C++, which seems to be what the OP asked for
Michael Mrozek
@Michael That's not how I interpret it at all. It sounds like he wants the ability to call a function when something gets changed, and to do it in C++. It doesn't seem to specify built in or not, at least to these eyes.
glowcoder
@glow I guess he'd probably be happy with any solution, but "Is there a function in c++" makes me think he just wants to call `detect_changes(`
Michael Mrozek
+2  A: 

No, you should encapsulate the variable in a couple of get/set methods.

munissor
+3  A: 

You could make the variable private to some class and then use member functions for the change in the first place.

You could put your extra code into the member function itself, or you can have that code separate and have the member function call it on change.

Platinum Azure
+10  A: 

Is there a function in c++ that when a variable got changed it automatically call a function?

No, not that I could think of. You can, however, wrap access to the variable in a suitable wrapper which allows you to hook into assignment.
Something like this:

//Beware, brain-compiled code ahead!
template<typename T>
class assignment_hook {
public:
  typedef void (hook_t)(const T& old_value, const T& new_value);

  assignment_hook(T& value, hook_t hook) : ref_(value), hook_(hook)  {}

  T& operator=(const T& rhs)
  {
     hook_(ref_,rhs);
     ref_ = rhs;
  }
private:
  // I'd rather not want to think about copying this
  assignment_hook(const assignment_hook&);
  void operator=(const assignment_hook&);

  T& ref_;
  hook_t hook_;
};

As Noah noted in a comment,

typedef boost::function<void(const T&,const T&)> hook_t;

(or, if your compiler has it, std::tr1::function or std::function) would greatly improve on that, because it allows all kinds of "compatible" functions to be called. (For example, it enables all kinds of magic using boost/std::/tr1::bind<> to call member functions and whatnot.)

Also note that, as adf88 said in his comments, this just does what was asked for (monitor write access to a variable) and is by no means a full-fledged property implementation. In fact, despite C++' attitude to implement as much as possible in libraries and as little as possible in the language, and despite the attempts of many people (some of them rather smart ones), nobody has found a way to implement properties in C++ as a library, without support from the language.

sbi
Don't you think it complicates too much? What about other operators? What about taking an address? You brake semantics here. If the compiler don't support Properties then it's not a good solution to simulate them. -1
adf88
@adf88: what do you mean, "complicates too much"? If you want to do what the questioner asked, then this is about as simple as it gets. As for your last point, the compiler doesn't directly support resizable arrays, function objects, smart pointers, template metaprogramming, or many other concepts which have become common (or even standard) C++ idioms by writing code to "simulate" them.
Mike Seymour
Use of boost::function and/or boost::signals(2) would make this a better solution imho.
Noah Roberts
Overwriting the = operator..what a cool trick. IMHO, way better than the getter/setter hacks recommended by Java-polluted thinking. In some Java projects, I've been fighting getter/setter junk and always wished we could override the = operator like above. A good example is a variable you set once at run-time and throw an exception if set again.
User1
@adf88: Taking the address wasn't asked for. Nor any other operation, FTM. As Mike said: Most of C++ is implemented as libraries. If we would have to stick to what the compiler provides, we'd be stuck in the 80ies. (And everyone who remembers their music doesn't want to go back there!)
sbi
@User1: `struct Test { Test(int i) : i_(i) {} const int i_; };` would catch attempts to change `i_` at compile time.
sbi
@Noah: I actually thought about boost::function<>, but then I didn't want to spoil this easy solution with it. I meant to mention it, though, but forgot about it. So thank you for bringing this up. I'll add a hint at it to the answer.
sbi
It is impossible to simulate properties in c++ (I mentioned many problems). Any implementation wouldn't be good, wouldn't be hermetic. Taking an address is very important here - compiler won't warn you if you do so. Simple setter/getter is the best here because it protects you from making mistakes.
adf88
@adf88: If you read carefully, you'll see that it was you who brought up the term "Properties". Strawman?
sbi
It's no matter how would you name this. It's not hermetic and can lead to mistakes.
adf88
@adf88: No, it's not hermetic, it does just what was asked fro and nothing else. But then, nobody had claimed it would be hermetic and failsafe. That's just a strawman you keep knocking at.
sbi
@User1: if youre only allowed to set/assign it once, why not simply put it in the constructor?
Viktor Sehr
Last few words from me: "it does just what was asked fro and nothing else" - your right, but your answer is not good. Why? If someone don't know how to do something then sometimes he/she imagine some bad solutions, bad concept. You wrote a solution realizing bad concept. You are messing up in noob's head. Obvious answer is to change the concept - don't "detect" when the variable is changed; instead write a function and call this function in places where you were setting value of the variable.
adf88
@adf88: I can see that it might help to add a warning to my answer and I went and did so. I still believe, however, that for the task give, this is a good and valid solution.
sbi
+1  A: 

Depending on the complexity of your program, you could use Listeners that monitor certain objects for state changes, and have other parts of your program subscribe for events from that listener.

However, the best option would be to put this functionality into the setter method for that variable. It could be listener functionality, or a direct function call.

glowcoder
A: 

You can encapsulate that variable, and have listeners that are notified when the value changes. I'd go with boost::signals or boost::signals2 for that :

http://www.boost.org/doc/libs/1_43_0/doc/html/signals2.html

and here's some info on the observer pattern : http://en.wikipedia.org/wiki/Observer_pattern

fingerprint211b
A: 

If the variable has a class type, you can overload its operator =() function. You cannot do this if the variable is a primitive type.

Loadmaster