I know that the implementation of property-like objects has been discussed many times, but what I need is slightly different from the various solutions proposed.
What I want is an object that has the same semantics of a variable, but when its value is changed I want to perform some action. This means having implicit get/set methods, implemented overloading the operator = and the implicit conversion operator.
Please note that when I mean "property-like" I don't mean necessarily the semantic object.property
, but just a way to have implicit get/set methods (as in property-like-variable = value
). The reason is that I have some existing code that uses a variable, I want to perform some action every time the variable value changes without changing the existing code (only the declaration of the variable should change).
I have obtained this result with a minimal code like this:
#include <stdio.h>
class Int
{
int _value;
public:
// default constructor
Int() { printf("Int: initial value undefined\n"); }
// assignment constructor
Int(int value) : _value(value) { printf("Int: initial value is %d\n", _value); }
// property get
operator const int() const { return _value; }
// property set
int operator=(int value)
{
_value = value;
printf("new value is %d\n", value);
return value;
}
// TODO: overload other operators if needed
};
This is a sample usage:
class C
{
Int _i;
public:
C() : _i(2) { }
void foo()
{
_i = 3;
printf("foo(): _i = %d\n", _i);
}
};
int main()
{
int i;
Int I;
i = 1;
I = i;
I = I + 1;
C c;
c.foo();
}
Now some questions:
Ad question 2: I see two general issues with your code:
the first const qualifier in your operator const int()
declaration is meaningless (gcc warns about it)
the return type of the assignment operator should be Int&
not int
otherwise it will have different semantics than the one of the original int and the following c++ code will not compile:
Int i;
(i=2)=3;
Ad question 3: if your set/get functions do nothing but assign/return the value they should be optimized out completely. If you call printf()
though, you might seriously get into performance trouble ;).
Ad question 5: The generalization with templates seems strait forward, including customizing it for different types via template sepcialization:
template<typename T> class observe
{
T _value;
public:
// default constructor
observe() { cout << "Int: initial value undefined" << endl; }
// assignment constructor
observe(const T& v) : _value(v) { cout << "initial value is " << v << endl; }
// property get
operator T() const { return _value; }
// property set
observe<T>& operator=(const T& value)
{
_value = value;
cout << "new value is " << _value << endl;
return *this;
}
};
// special behavior for the assignment of doubles
template<> observe<double>& observe<double>::operator =(const double& value)
{
_value = value;
cout << "new double value is " << _value << endl;
return *this;
}
observe<double> d;
d = 1.0;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With