ariya.io About Collections Archives

Property in C++

4 min read

Almost ten years ago a friend of mine showed that he was happy to use
Visual Basic’s (and also later on Delphi’s, with Borland’s extensions to Pascal)
feature of object property, which allows one to set a property of an object
and have the object respond to the change. For example, this code:

Button1.Left = 43

will automagically also move that button to a new position, not only

changing Left to a new value. In C++, this is not achievable

because no function call is involved. Instead, the code must be

modified to something like:

Button1.SetLeft(43);

And we need to have another (getter) method to obtain the property’s

value:

int posx = Button1.Left();

while in VB and Delphi’s Pascal, one Left is enough.

Personally, I believe this is only syntax stuff. It doesn’t matter so much,

it even improves nothing. But just to make a rebuttal, I crafted a simple

example to show that it is also possible to implement such feature in C++.

The key here is that each property is an object. To cover all basic

data type, obviously template-based is a good choice:

template<class t="T">
class Property
{
public:
 Property(){ owner = ; };
 operator T(){ return data; }
 Property( T dat ){ data = dat; }
 void setup( Object* obj, std::string n ){ owner = obj; name = n; }
 Property& operator=( T dat ){ 
  bool changed = dat!=data; data = dat; 
  if(owner && changed) owner->propertyChanged(name);return *this; }
private:
 T data;
 Object* owner;
 std::string name;
};
</class>

Later on, to wrap that setup() method, a simple macro magic is employed:

#define INIT_PROPERTY(x)  (x).setup( this, #x )

The basic object system needs to have method to be called when its

properties are modified:

class Object
{
public:
  virtual void propertyChanged( std::string name ) = ;
};

As you can guess already, propertyChanged is invoked

when a new value is assigned to the property. So the secret is here

is the overloaded assignment operator.

A hypotetical widget named Slider can be implemented as follows:

class Slider: public Object
{
public:
  Slider();
  virtual void propertyChanged( std::string name );
  Property<int> min;
  Property</int><int> max;
  Property<double> value;
};
</double></int>

Properties of this Slider must be initialized in the constructor. This is

so that each will get a unique name and assigned to an object (simply

this) to which it will report when its value is changed.

With the INIT_PROPERTY macro, this is as convenient as:

Slider::Slider()
{
  std::cout < < "Creating slider" << std::endl;
  INIT_PROPERTY( min );
  INIT_PROPERTY( max );
  INIT_PROPERTY( value );
}

The job of propertyChanged is then to handle the situation when

one of the property has been changed:

void Slider::propertyChanged( std::string name )
{
  if( name == "min" )
     {
     std::cout < < "Slider.min has been changed" << std::endl;
     // do something
     }
 
  if( name == "max" )
     {
     std::cout << "Slider.max has been changed" << std::endl;
     // do something
     }
 
  if( name == "value" )
     {
     std::cout << "Slider.value has been changed" << std::endl;
     // do something
     }
}

Almost nothing else is needed. Then, the code snippet shown below is

already comparable to how it is done in VB:

&nbsp; Slider slider;
&nbsp; slider.min = 1;
&nbsp; slider.max = 42;
&nbsp; slider.value = 8.3;

Althought is a “fake implementation”, at least I have convinced

my friend that C++ can have property.

Of course, this trick has some disadvantages. Properties needs to be

initialized in the class constructor, so more boilerplate code compared

to the case where this kind of feature is supported in the language itself.

No checking when setting a value means corner cases must be well taken care of.

Also, properties are object instances which are not so cheap. Comparing

the property using string is also not fast.

Infinite loop is even possible when it is not handled well.

I believe that some functors in combination with more template and macro

magic will even allow the redirection of reading and writing property to

the corresponding getter and setter methods. Left as an

exercise for the reader 😛

Related posts:

♡ this article? Explore more, check the archives, or follow me Twitter.

Share this on Twitter Facebook Google+

comments powered by Disqus